objectとcase class


object

Scalaではすべての値がオブジェクトのため、クラスに属するstaticフィールドやstaticメソッドを作成できません。しかし、objectキーワードによって同じ名前のシングルトンオブジェクトをグローバルな名前空間に1つ定義できます。

オブジェクトキーワードによって定義したオブジェクトもオブジェクトであるため、メソッドやフィールドを定義できます。

objectの主な用途は次の通りです。

  • ユーティリティやグローバルな状態の置き場(Javaで言うstaticメソッドやstaticフィールド)
  • オブジェクトのファクトリメソッド
  • シングルトンパターン

基本的には最初の2つの用途で使われます。

applyメソッド

Scalaのobjectにおいてapplyという名前のメソッドは特別に扱われます。

object Point {
  def apply(x: Int, y: Int): Point = new Point(x, y)
}
Point(2, 4)

Point1(x)のような記述があった場合でPointオブジェクトにapplyというメソッドが定義されていた場合、Point(x)はPoin1.apply(x)と解釈されます。

これを利用してPointオブジェクトのapplyメソッドでオブジェクトを生成しようとすることで、Point(1, 2)のような記述でオブジェクトの生成ができます。

これはnew Point()で直接Pointオブジェクトを生成するのに比べて次のようなメリットがります。

  • クラス(Point)の実装詳細を内部に隠しておける(インターフェースのみを外部に公開する)
  • Pointではなく、そのサブクラスのインスタンスを返すことができる。

case class

case classとは、それを付けたクラスのプライマリーコンストラクタすべてのフィールドを公開し、 equals(), hashCode(), toString()などのオブジェクトの基本的なメソッドを持ったクラスを生成します。

また、そのクラスのインスタンスを生成するためのファクトリメソッドを生成します。

case class Point2(x: Int, y: Int)
println(Point2(1, 2).equals(Porint2(1, 2) ) )
// equalsメソッドを定義していないがequalsメソッドを使用できます

クラス名と同じ名前のシングルトンオブジェクトはコンパニオンオブジェクトと呼ばれます。

コンパニオンオブジェクトは対応するクラスに対して特権的なアクセス権を持っています。

class Person(name: String, private age: Int)

object human {
  def printAge(): Unit = {
    val taro = new Person("taro", 22)
    println(taro.age)
  }
}
// コンパニオンオブジェクトはクラスのprivateにアクセスすることができます
// しかし、private[this]にはアクセスできません