ケースクラスの2つ目の引数が外から見えない、なぜだろう?ということが発端となり、いろいろと調べたりGitterで質問してみました。その結果、コンストラクタ引数の定義のしかたによって見え方(アクセス修飾子の状態)が異なるということがわかりました。


scala> case class A(x: Int)(y: Int){

     | def printY() = println(y)

     | }

defined class A

scala> val a = A(10)(20)

a: A = A(10)

scala> a.x

res22: Int = 10

scala> a.y

<console>:19: error: value y is not a member of A

              a.y

                ^

scala> a.printY()

20

クラスののデフォルトコンストラクタ引数はprivateです。したがって、下の例ではprivateなフィールドxにアクセスしようとしてエラーが出ています。


scala> class A(x: Int)

defined class A

scala> new A(10)

res0: A = A@af23093

scala> res0.x

<console>:13: error: value x is not a member of A

       res0.x

            ^

scala> 

私は普段case classをよく使う一方、クラスのフィールドに外からアクセスすることはあまりないので、すっかり頭のなかから抜け落ちていました。

このフィールドをpublicなものとするには、 val または var を明示的に付けてあげる必要があります。


scala> class A(val x: Int)

defined class A

scala> new A(10)

res0: A = A@6deaf732

scala> res0.x

res1: Int = 10

あるいは、case classとすると、valやvarを付加しなくても自動生成されたゲッターメソッドによってフィールドにアクセスできます。


scala> case class A(x: Int)

defined class A

scala> A(10)

res0: A = A(10)

scala> res0.x

res1: Int = 10

しかしながら、case classは万能ではありません。case classに複数のパラメータリストが存在する場合、2つ目以降のパラメータリストにはゲッターメソッドを生成してくれません。


scala>  case class B(x: Int)(y: Int)(z: Int)

defined class B

scala> B(10)(20)(30)

res0: B = B(10)

scala> res0.x

res1: Int = 10

scala> res0.y

<console>:14: error: value y is not a member of B

       res0.y

            ^

scala> res0.z

<console>:14: error: value z is not a member of B

       res0.z

            ^

それどころか、case classはequals()やhashCode()についても2つ目以降のパラメータリストを無視してくれるので、以下のように「第一パラメータだけで比較する」「ハッシュコードが同一になる」といった現象が起こります。
https://gitter.im/scalajp/public


scala> case class C(x: Int)(y: Int)

defined class C

scala> C(10)(20)

res0: C = C(10)

scala> C(10)(30)

res1: C = C(10)

scala> res0 == res1

res2: Boolean = true

scala> res0.hashCode

res3: Int = -2008924253

scala> res1.hashCode

res4: Int = -2008924253

結論:気をつけます。

参考


http://www.ne.jp/asahi/hishidama/home/tech/scala/class.html#h_construntor


http://www.ne.jp/asahi/hishidama/home/tech/scala/class.html#h_case_class