2017-11-29 5 views
0

コンパニオンオブジェクトを持つクラスTestClassがあります。以下のようにクラス内からプライベートフィールドが設定されている場合、スカラでランタイムリフレクションを使用してコンパニオンオブジェクト内のプライベートフィールドxyzにアクセスするにはどうすればよいですか。コンパニオンオブジェクトのプライベートフィールドにアクセス

class TestClass { TestClass.xyz = 100 } 
object TestClass { private var xyz: Int = _ } 

私は、次の

import scala.reflect.runtime.{currentMirror, universe => ru} 
val testModuleSymbol = ru.typeOf[TestClass.type].termSymbol.asModule 
val moduleMirror = currentMirror.reflectModule(testModuleSymbol) 
val instanceMirror = currentMirror.reflect(moduleMirror.instance) 
val xyzTerm = ru.typeOf[TestClass.type].decl(ru.TermName("xyz")).asTerm.accessed.asTerm 
val fieldMirror = instanceMirror.reflectField(xyzTerm) 
val context = fieldMirror.get.asInstanceOf[Int] 

を試みたが、私は以下のエラーを取得しました。

scala> val fieldMirror = instanceMirror.reflectField(xyzTerm) 
scala.ScalaReflectionException: Scala field xyz of object TestClass isn't represented as a Java field, nor does it have a 
Java accessor method. One common reason for this is that it may be a private class parameter 
not used outside the primary constructor. 
    at scala.reflect.runtime.JavaMirrors$JavaMirror.scala$reflect$runtime$JavaMirrors$JavaMirror$$abort(JavaMirrors.scala:115) 
    at scala.reflect.runtime.JavaMirrors$JavaMirror.scala$reflect$runtime$JavaMirrors$JavaMirror$$ErrorNonExistentField(JavaMirrors.scala:127) 
    at scala.reflect.runtime.JavaMirrors$JavaMirror$JavaInstanceMirror.reflectField(JavaMirrors.scala:242) 
    at scala.reflect.runtime.JavaMirrors$JavaMirror$JavaInstanceMirror.reflectField(JavaMirrors.scala:233) 
    ... 29 elided 

私はTestClassを変数xyzを参照する場合にのみ、この例外は(すなわちTestClass.xyz = 100)スローされます。この参照がクラスから削除されている場合、私のサンプルコードは正常に動作します。

import scala.reflect.runtime.universe._ 
import scala.reflect.runtime.{universe => ru} 

val runMirror = ru.runtimeMirror(getClass.getClassLoader) 
val objectDef = Class.forName("org.myorg.TestClass") 
val objectTypeModule = runMirror.moduleSymbol(objectDef).asModule 
val objectType = objectTypeModule.typeSignature 

val methodMap = objectType.members 
    .filter(_.isMethod) 
    .map(d => { 
    d.name.toString -> d.asMethod 
    }) 
    .toMap 

// get the scala Object 
val instance = runMirror.reflectModule(objectTypeModule).instance 
val instanceMirror = runMirror.reflect(instance) 
// get the private value 
val result = instanceMirror.reflectMethod(methodMap("xyz")).apply() 
assert(result == 100) 

答えて

1

が、これは動作するようになりました
関連する問題