Scalaにおけるシングルトンオブジェクトとは

Playの本を読んでいたらシングルトンオブジェクトを利用するコードをよく目にしたのでメモ。

シングルトンオブジェクト

Scala特有の機能がシングルトンオブジェクトの定義だ。ScalaJavaとは違って静的なメンバを持つ事ができないが、シングルトンオブジェクトを作る事でJavaの静的な関数のように扱う事ができる。

object ChecksumAccumulator {
    private val cache = Map[String, Int]()
    def calculate(s: String): Int =
    ....
}

コンパニオンクラス

シングルトンオブジェクトが同名のクラスを持つとき、それをコンパニオンオブジェクトと呼ぶ。クラスとコンパニオンオブジェクトは同じソースファイルで定義しなければならないが、それらは互いの非公開メンバーにアクセスできるという特徴を持つ。

class Rocket {
  import Rocket.fuel
  private def canGoHomeAgain = fuel > 20
}

object Rocket {
  private def fuel = 10
  def chooseStrategy(rocket: Rocket) : String = {
    if (rocket.canGoHomeAgain)
      goHome()
    else
      pickAStar()
  }
  
  def goHome() : String = { "goHome" }
  def pickAStar() : String = { "pickAStar" }
}

利用例

これは以下のように呼び出せる。

$ var rocket = new Rocket
$ Rocket.chooseStrategy(rocket)
> goHome

rocketクラスを作成し、コンパニオンオブジェクトのchooseStrategy関数をrocketを引数にして呼び出す。すると、privateで宣言されているRocketクラスのcanGoHomeAgain関数を呼び出せる。