제거됨: 패키지 객체

제거됨: 패키지 객체 (Package Objects)

패키지 객체(package object)는 Scala 3에서 제거될 예정이에요. 아직은 쓸 수 있지만, 언젠가 deprecated가 되고 이후에 제거됩니다.

출처: Scala 3 Reference

본문

패키지 객체

package object p {
  val a = ...
  def b = ...
}

는 제거될 예정이에요. 아직은 사용할 수 있지만, 가까운 미래에 deprecated되고 제거됩니다.

패키지 객체는 이제 더 이상 필요하지 않아요. 모든 종류의 정의를 최상위 레벨(top-level)에 쓸 수 있게 됐기 때문이에요. 예시:

package p
type Labelled[T] = (String, T)
val a: Labelled[Int] = ("count", 1)
def b = a._2

case class C()

extension (x: C) def pair(y: C) = (x, y)

한 패키지 안에 이런 최상위 정의를 담은 소스 파일이 여러 개 있을 수 있고, 소스 파일은 최상위 값·메서드·타입 정의를 클래스나 객체와 자유롭게 섞어 쓸 수 있어요.

컴파일러는 다음 범주에 속하는 최상위 정의를 감싸는 합성 객체(synthetic object)를 만들어내요.

  • 모든 패턴, 값, 메서드, 타입 정의
  • 암시적 클래스(implicit class)와 객체
  • 불투명 타입 별칭(opaque type alias)의 컴패니언 객체

소스 파일 src.scala에 이런 최상위 정의가 있으면, 그 정의들은 src$package라는 이름의 합성 객체에 들어가요. 하지만 이 감싸기는 투명해서, src 안의 정의는 여전히 포함하는 패키지의 멤버로 접근할 수 있어요. 합성 객체는 파일의 다른 패키지 절, 임포트, 객체·클래스 정의보다 뒤인 파일 맨 마지막에 배치됩니다.

참고: 이 말은 즉,

  • 감싸인 최상위 정의를 담은 소스 파일의 이름은 바이너리 호환성에 영향을 줘요. 이름이 바뀌면 생성되는 객체와 그 클래스의 이름도 바뀌니까요.
  • 최상위 main 메서드 def main(args: Array[String]): Unit = ...도 다른 메서드처럼 감싸여요. 이 메서드가 소스 파일 src.scala에 있으면 scala src$package 같은 명령으로 커맨드 라인에서 호출할 수 있어요. "프로그램 이름"이 맹글링(mangle)되기 때문에, main 메서드는 항상 이름이 명시된 객체에 두는 걸 권장해요.
  • private의 의미는 정의가 감싸였는지와는 무관해요. private 최상위 정의는 포함하는 패키지 안 어디에서나 항상 보입니다.
  • 같은 이름을 가진 여러 최상위 정의가 오버로드된 변형이라면, 반드시 같은 소스 파일에서 와야 해요.

더 알아보기 (Learn more)