Scalaのobjectについてまとめてみた

今回はscalaのオブジェクトについて調べてみたので、どこまで理解しているかも含めブログに書いておきます。
ここは。。という点あればどんどん指摘お願いします。

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

Scalaのclassとobjectの違いですが、classはいわゆる通常のクラスの同じです。
Scalaのクラスではstaticな変数やメソッドを定義することが出来ません。
その代わりに、object(シングルトン)を使います。objectキーワードによって定義したオブジェクトにメソッドやフィールドを持たせることができます。
またクラスと違い、コンストラクタを明示的に定義することはできません。

objectキーワードで通常のクラスのようにnewでインスタンスを生成しなくても、定義したオブジェクトのフィールドやメソッドを利用できます。

scala> class Performance(val capacity: Int, val display: Double, val weight: Int){
     | override def toString = {
     | "capacity: %d GB display: %.1f inch weight: %d g" format(capacity, display, weight)
     | }
     | }
defined class Performance

scala> object GalaxyS3 {
     | val performance = new performance(32, 4.7, 200)
     | val brand = "Sumsung"
     | }
defined object GalaxyS3

scala> GalaxyS3.performance
res1: performance = capacity: 32 GB display: 4.7 inch weight: 200 g

scala> GalaxyS3.brand
res2: String = Sumsung

・コンパニオンオブジェクト

コンパニオンオブジェクトとは、同スコープ内(同一ファイル内・同ブロック内)で定義されたクラス名と同じ名前のシングルトンオブジェクトです。
それに対してコンパニオンオブジェクトが属しているクラスをコンパニオンクラスといいます。
scalaではstaticキーワードがないためクラスにstaticなメンバを持たせることができません。
なのでobjectキーワードによって定義したオブジェクトにメンバを持たせることで、クラス内部のprivateなメンバを参照できます。

では例を見ていきます。

class SmartPhone private(val color:String, val price:Int, maker:String){
  def this(color:String, maker:String) = this(color, 500, maker)
    override def toString = {
      "color: %s, price: $%d, maker: %s"format(color, price, maker)
    }
}
object SmartPhone {
  def apply(color:String, price:Int, maker:String) = new SmartPhone(color, price, maker)
}

// Exiting paste mode, now interpreting.

defined class SmartPhone
defined object SmartPhone

scala> SmartPhone("blue", 900, "Apple")
res10: SmartPhone = color: blue, price: $900, maker: Apple

↑コンパニオンオブジェクトSmartPhoneからコンパニオンクラスのメンバにアクセスできていることが確認できます。
この逆も可能で、コンパニオンオブジェクトのprivateメンバにコンパニオンクラスからアクセスも可能です。

またシングルトンオブジェクトは最初にアクセスされた時に初期化されます。
実際にコードで見てみましょう。

class SmartPhone private(val color:String, val price:Int, maker:String){
  def this(color:String, maker:String) = this(color, 500, maker)
    override def toString = {
      "color: %s, price: $%d, maker: %s"format(color, price, maker)
    }
}
object SmartPhone {
  println("初期化されました")
  def apply(color:String, price:Int, maker:String) = new SmartPhone(color, price, maker)
}

// Exiting paste mode, now interpreting.

defined class SmartPhone
defined object SmartPhone

scala> SmartPhone
初期化されました
res11: SmartPhone.type = SmartPhone$@1eb6749b

↑はシングルトンオブジェクトにアクセスされた際に初期化されていることが分かります。

このようにScalaではstaticなメンバを作成できないため、同様のことをしたい場合はobjectキーワードで、コンパニオンオブジェクトとコンパニオンクラスのお互いのprivateなメンバーにアクセスします。

参考サイト
http://dany1468.tumblr.com/post/308257173/scala
http://aya-eiya.hateblo.jp/entry/20110219/1298121073