getDeclaredFieldsとtrait

case classのフィールドをリフレクションで取得するときの話。


以下REPLで

scala> case class A(a: String, b: Int)
defined class A

scala> val a = classOf[A]
a: java.lang.Class[A] = class A

scala> a.getDeclaredFields
res0: Array[java.lang.reflect.Field] = Array(private final java.lang.String A.a, private final int A.b)

フィールドを持つtraitを継承させたcase classだと、traitのフィールドも含まれてしまう。。
(試してないからわかんないけど、Javaのinterface定数でもこうなるのかな?)

scala> trait Base{
     |   var base1: String = _
     |   var base2: String = _
     | }
defined trait Base

scala> case class B(a: String, b: Int) extends Base
defined class B

scala> val b = classOf[B]
b: java.lang.Class[B] = class B

scala> b.getDeclaredFields
res1: Array[java.lang.reflect.Field] = Array(private final java.lang.String B.a, private final int B.b, private java.lang.String B.base1, private java.lang.String B.base2)

仕方ないからabstract classを使うことにした。

scala> abstract class AbstractBase{
     |   var base1: String = _
     |   var base2: String = _
     | }
defined class AbstractBase

scala> case class C(a: String, b: Int) extends AbstractBase
defined class C

scala> val c = classOf[C]
c: java.lang.Class[C] = class C

scala> c.getDeclaredFields
res2: Array[java.lang.reflect.Field] = Array(private final java.lang.String C.a, private final int C.b)

それにしてもREPLは補完が効くし大変素晴らしい。
IDEなんか初めからいらんかったんや!