싱글톤 객체

클래스의 각 인스턴스와 연관되지 않은 메서드와 값들은 싱글톤 객체에 속하며, class대신에 object를 사용해 표시된다.

package test

object Blah {
  def sum(l: List[Int]): Int = l.sum
}

sum메서드는 전역적으로 접근가능하고 참조될수 있으며, test.Blah.sum로 import될수 있다.

싱글턴 객체는 직접 인스턴스화 될 수 없는 싱글턴 클래스를 정의하기 위한 축약형 같은 것이며, object의 정의 시점의 같은 이름을 가진 val 멤버 같은 것이다. 사실 val과 같이, 싱글턴 객체는 변칙적이긴 하지만 트레잇이나 클래스의 멤버로서 정의될수 있다.

하나의 싱글턴 객체는 클래스와 트레잇으로 확장할수 있다. 사실, 타입 파라미터가 없는 케이스 클래스는 기본적으로 같은 이름의 싱글턴 객체를 생성하며, 구현된 Function*을 가진다.

동반자(Companions)

대부분의 싱글턴 객체는 독립적이지 않으며, 대신에 같은 이름의 클래스와 연관되어있다. 위에서 언급한 클래스의 “같은 이름의 싱글턴 객체”는 이 예이다. 이 현상이 발생할 때, 싱글턴 객체는 클래스의 동반자 객체 라고 하며, 그 클래스는 객체의 동반자 클래스라고 한다.

스칼라 문서는 클래스와 그 동반자 사이의 이동을 위한 특별한 지원을 가지고 있다. 만약 큰 “C”나 “O” 원이 아래에서 위로 접힌 경계를 가진다면, 여러분은 동반자로 이동하기 위해 해당 원을 클릭할수 있다.

하나의 클래스와 그 동반자 객체는 어떤 경우라도, 아래와 같이 같은 소스파일에 정의되어야 한다.

class IntPair(val x: Int, val y: Int)

object IntPair {
  import math.Ordering

  implicit def ipord: Ordering[IntPair] =
    Ordering.by(ip => (ip.x, ip.y))
}

타입클래스 패턴을 따를때, 일반적으로 타입클래스 인스턴스들을 동반자 안에 정의된 ipord와 같은 암시적 값들로 생각한다.

자바 프로그래머들이 주의할 점

static은 스칼라에서 키워드가 아니다. 대신에 class를 포함한 static일 수 있는 모든 멤버는 싱글턴 객체에 있어야 한다. 그것들은 부분적으로 또는 그룹 등등으로 import될수 있으며, 같은 문법으로 참조될수 있다.

빈번하게, 자바프로그래머들은 그 인스턴스 멤버를 목적으로 구현 할때 private을 사용해 static 멤버를 정의한다. 이것들은 또한 동반자(companion)으로 이동되었다. 일반적인 패턴은 아래와 같이 동반자 객체(object)의 멤버들을 클래스 안으로 import하는 것이다.

class X {
  import X._

  def blah = foo
}

object X {
  private def foo = 42
}

이것은 또 다른 특징을 설명한다. private의 문맥에서 클래스와 그 동반자는 친구다. 객체 X클래스 X의 private 멤버들에 접근할수 있다. 하나의 멤버를 정말로 private하게 만들고 싶다면 private[this]를 사용하라.

For Java convenience, methods, including vars and vals, defined directly in a singleton object also have a static method defined in the companion class, called a static forwarder. Other members are accessible via the X$.MODULE$ static field for object X.

자바 편의를 위해서, varval의 것 모두, 싱글턴 객체에 정의된 메서드들은 static forwarder 라고 불리는 동반자 클래스안에 정의된 static메서드를 가진다. 다른 멤버들은 객체 X를 위한 static 필드 X$.MODULE$를 통해 접근할수 있다.

만약 당신이 모든 것을 동반자 객체에 옮기고, 당신이 남겨놓은 모든것이 인스턴스화가 되길 바라지 않는 하나의 클래스라면, 간단하게 그 클래스를 삭제하라. Static forwarder는 여전히 생성된다.