Programming in Sala 책으로 스칼라 스터디하면서 정리했던 내용이다. 지금은 3판 번역본도 나왔지만, 약간 앞서서 스터디를 시작해서 2판으로 진행했다.

13장

패키지

  • 파일 전체를 패키지 안에 넣기
package bobsrockets.navigation
class Navigator
  • 패키징 문법
package bobsrockets.navigation {
  class Navigator
}
  • 여러 패키지
package bobsrockets {
  package navigation {
    class Navigator

    package tests {
      class NavigatorSuite
    }
}

관련 코드 접근

  • 클래스가 속한 패키지 안에서는 접두어 없이 해당 클래스에 접근 가능
  • 패키지를 포함하는 부모 패키지는 접두어 없이 해당 패키지 접근 가능
  • 중괄호 패키징 문법을 사용하면 패키징 스코프 밖에서 접근 가능한 모든 이름을 패키징 안에서 사용 가능
package bobsrockets {
  package navigation {
    class Navigator {
      val map = new StarMap // bobsrockets.navigation.StarMap
    }
    class StarMap
  }

  class Ship {
    val nav = new navigation.Navigator  // bobsrockets.navigation.Navigator
  }

  package fleets {
    class Fleet {
      def addShip() {
        new Ship        // bobsrockets.Ship
      }
    }
  }
}
  • 연쇄 패키지 절 : 괄호 없이 여러 패키지 절 사용
package bobsrockets // 중괄호 생략
package fleets      // 중괄호 생략
class Fleet {
  def addShip() { new Ship }
}
  • 숨겨진 패키지 이름 접근
package launch {
  class Booster3
}

package bobsrockets {
  package navigation {
    package launch {
      class Booster1
    }

    class MissionControl {
      val booster1 = new launch.Booster1                // 가장 좁은 패키지 스코프 안에 있음
      val booster2 = new bobsrockets.launch.Booster2    // 전체 패키지 지정
      val booster3 = new _root_.launch.Booster3         // 최상위 launch 패키지
    }
  }

  package launch {
    class Booster2
  }
}

임포트

  • 자바의 싱글 타입 임포트
// Fruit
import bobsdelights.Fruit
  • 자바의 주문식 임포트(*)
// bobsdelights의 모든 멤버
import bobsdelights._
  • 자바의 정적 클래스 필드 임포트
// Fruit의 모든 멤버
import bobsdelights.Fruits._
  • import 문은 코드 어디에나 위치 가능
def showFruit(fruit: Fruit) {
  import fruit._
  println(name +"s are"+ color) // fruit.name, fruit.color
}
  • 패키지, 객체 참조 가능
import java.util.regex
class AStarB {
  val pat = regex.Pattern.compile("a*b")    // 싱글톤 객체 java.util.regex.Pattern
}
  • 불러온 멤버 이름 중 일부를 숨기거나 다른 이름 지정 가능
    • x : x를 불러온다
    • x => y : x를 y라는 이름으로 불러온다
    • x => _ : x를 제외하고 불러온다
    • _ : 나머지를 모두 가져온다
// 일부 멤버만 불러온다
import Fruits.{Apple, Orange}

// 다른 이름 지정
import Fruits.{Apple => McIntosh, Orange}

// import Fruits._ 과 동일
import Fruits.{_}

// import Fruits._ 과 동일하나 Apple의 이름만 바꾼다
import Fruits.{Apple => McIntosh, _}

// Pear를 제외한 모든 멤버를 불러온다
import Fruits.{Pear => _, _}

암시적 임포트

  • 세가지 임포트 절을 모든 스칼라 소스 위에 추가하는 것과 같은 동작 있음
import java.lang._
import scala._
import.Predef._
  • 나중에 임포트한 패키지에 들어있는 이름이 앞에서 임포트한 이름을 가리게 됨

접근 수식자

비공개 멤버 private

자바와 달리 외부 클래스가 내부 클래스에 있는 비공개 멤버에 접근 불가

class Outer {
  class Inner {
    private def f() { ... }
    class InnerMost {
      f() // 문제 없음
    }
  }

  (new Inner).f()   // 오류
}

보호 멤버 protected

자바와 달리 보호 멤버를 정의한 클래스의 서브클래스에서만 접근 가능

package p {
  class Super {
    protected def f() { ... }
  }

  class Sub extends Super {
    f() // 문제 없음
  }

  class Other {
    (new Super).f() // 오류
  }
}

공개 멤버

privateprotected가 없는 멤버

보호 스코프

package bobsrockets

package navigation {
  private[bobsrockets] class Navigator {    // bobsrockets 내부에서 접근 가능
    protected[navigation] def useStarChart() {} // bobsrockets.navigation 내부와 bobsrockets.navigation.Navigator 서브 클래스에서 접근 가능
    
    class LegOfJourney {
      private[Navigator] val distance = 100 // bobsrockets.navigation.Navigator 내부에서 접근 가능
    }
    private[this] var speed = 200   // bobsrockets.navigation.Navigator 클래스의 객체 자신만 접근
  }
}

package launch {
  import navigation._
  object Vehicle {
    private[launch] val guide = new Navigator   // bobsrockets.launch 내부에서 접근 가능
  }
}
  • 수식자 없음 : 전체 접근 가능
  • private[bobsrockets] : bobsrockets 패키지 내부에서 접근 가능
  • private[navigation] : 자바의 패키지 접근
  • private[Navigator] : 자바의 private와 같음
  • private[LegOfJourney] : 스칼라의 private와 같음
  • private[this] : 어떤 객체 자신만 접근 가능

동반 객체

비공개, 보호 멤버에 대해서 동반 객체와 클래스는 접근 권리를 공유

패키지 객체

  • 패키지 전체 스코프에 도우미 메소드를 두는 경우, 패키지 최상위 수준에 넣을 수 있음
  • 패키지 객체는 package.class라는 이름의 클래스 파일로 컴파일되므로, 소스 파일도 동일하게 작성하는 것이 좋음
// bobsdelights/package.scala
package object bobsdelights {
  def showFruits(fruit : Fruit) {
    import fruit._
    println(name + "s are"+ color)
  }
}

// PrintMenu.scala
package printmenu
import bobsdelights.Fruits
import bobsdelights.showFruit
object PrintMenu {
  def main(args: Array[String]) {
    for (fruit <- Fruits.menu) {
      showFruit(fruit)
    }
  }
}


+ Recent posts