7

Scala で Java ライブラリ (JOhm) を使用しようとしていますが、ライブラリが Scala クラスのフィールドを次のようなもので読み取ろうとすると失敗することに気付きましたmodel.getClass().getDeclaredFields()

次に、Scala インタープリターで簡単な例を使用して同じことを試みることにしました。

scala> import java.lang.reflect.Field;
import java.lang.reflect.Field

scala> class myClass(attribute1: String, attribute2: String, attribute3: String)
defined class myClass

scala> val myInstance = new myClass("value1", "value2", "value3")
myInstance: myClass = myClass@7055c39a

scala> myInstance.getClass().getDeclaredFields()
res0: Array[java.lang.reflect.Field] = Array()

実際、フィールドはまったく得られません。

さて、これを試してみたらどうですか:

scala> class myClass2(attribute1: String, attribute2: String, attribute3: String) { override def toString = this.attribute1 }
defined class myClass2

scala> val myInstance2 = new myClass2("value1", "value2", "value3")
myInstance2: myClass2 = value1

scala> myInstance2.getClass().getDeclaredFields()
res1: Array[java.lang.reflect.Field] = Array(private final java.lang.String myClass2.attribute1)

そのため、クラスのメソッドの 1 つでフィールドの 1 つを使用すると、getDeclaredFields() によって検出されます。ここで何が欠けていますか?

4

3 に答える 3

1

フィールドをvalまたはとしてマークするとvar、次のgetDeclaredFieldsように検索されます。

class myClass(val attribute1: String)

JavaDoc forgetFieldsは、「アクセス可能なすべてのパブリック フィールド」を返すと述べているため、フィールドが明示的に公開されていない限り、フィールドがリストされていないことは理にかなっています (デフォルトでは、コンストラクターの引数はプライベート val です)。ただし、JavaDoc for にgetDeclaredFieldsはそのような制限については言及されていませんが、フィールドの可視性は明らかにここでも影響を及ぼします。


@Clémentに応じて編集:

import java.lang.reflect.Field

class Foo(val a1: String, private val a2: String, a3: String, a4: String) {
  val f = 10
  def foo(s: String) = a4 + s
}

val foo = new Foo("v1", "v2", "v3", "v4")

foo.getClass().getDeclaredFields().foreach(println)
  /* {a1, a2, a4, f} */

foo.getClass().getFields().foreach(println)
  /* {} */
于 2012-08-07T19:59:40.900 に答える
0

私の推測では、これは、Scala コンパイラーがすべてのコンストラクター引数に対してフィールドを生成しないためです。varまたはvalをクラス定義フィールドに追加すると、次のフィールドが生成されます。

scala> class myClass3(val attribute1:String, attribute2:String, attribute3:String)
defined class myClass3

scala> val myInstance3 = new myClass3("value1", "value2", "value3")
myInstance: myClass3 = myClass3@fd9178

scala> myInstance3.getClass().getDecalaredFields()
res1: Array[java.lang.reflect.Field] = Array(private field java.lang.String myClass3.attribute1)

最後の 2 つのコンストラクター パラメーターでは、フィールドが生成されないことに注意してください。これは、それらが単なるコンストラクタ パラメータであり、何もしないためです。関数をオーバーライドすると機能する理由toStringは、実際には、メソッドで引数にアクセスするときに使用される隠しフィールドをコンパイラが生成するためtoStringです。これに頼ってはいけないと思います。どのコンストラクターパラメーターがフィールドであるかを明示的に述べたほうがよいでしょう。

于 2012-08-07T20:06:39.627 に答える