私は Scala リフレクションを使用してトレイト ケース クラスを定義しようとしています。そのコンパニオンは、"エクスポート可能" (たとえば、Map[String,Any]) および "インポート可能" になるように実装できます。トップレベルのケースクラスではうまく機能していますが、内部クラスでは機能しません。InstanceMirror に反映できる、囲んでいるインスタンスのハンドルが既にある場合は、内部クラスを反射的にインスタンス化する方法を知っていますが、今のところ、トップレベルまたは内部クラスによって後で実装される特性を作成しています。 .
コンパニオンと構築されたインスタンスが同じ囲みインスタンスを共有する限り、これを機能させることができるはずです。しかし、コンパニオンの囲みインスタンスを反射的に決定する方法を理解できませんでした。
これは、私がやろうとしていることと発生する問題の簡単な例です。
import scala.reflect.runtime.universe._;
trait CompanionOfReflectiveConstructable[T] {
def tType : Type;
lazy val mirror : Mirror = runtimeMirror( this.getClass.getClassLoader );
lazy val ctorDecl : Symbol = tType.declaration(nme.CONSTRUCTOR);
lazy val ctor : MethodSymbol = ctorDecl.asMethod;
lazy val tClass : ClassSymbol = tType.typeSymbol.asClass;
lazy val tClassMirror : ClassMirror = mirror.reflectClass( tClass );
lazy val ctorF : MethodMirror = tClassMirror.reflectConstructor( ctor );
// in real-life, i'd derive arguments from ctor.paramss
// but to highlight our issue, we'll assume a no arg constructor
def createInstance : T = ctorF().asInstanceOf[T];
}
trait ReflectiveConstructable;
object Test1 extends CompanionOfReflectiveConstructable[Test1] {
def tType = typeOf[Test1];
}
class Test1 extends ReflectiveConstructable;
class Outer {
object Test2 extends CompanionOfReflectiveConstructable[Test2] {
def tType = typeOf[Test2];
}
class Test2 extends ReflectiveConstructable;
}
これが何が起こるかです。
scala> Test1.createInstance
res0: Test1 = Test1@2b52833d
scala> (new Outer).Test2.createInstance
scala.ScalaReflectionException: class Test2 is an inner class, use reflectClass on an InstanceMirror to obtain its ClassMirror
at scala.reflect.runtime.JavaMirrors$JavaMirror.ErrorInnerClass(JavaMirrors.scala:126)
...
Test1 はうまくいきます。Test2 の問題は明らかです。トップ レベルのミラーではなく、InstanceMirror を介して ClassMirror を取得する必要があります。(こちら、こちら、およびこちらを参照してください。) しかし、CompanionOfReflectiveConstructable 内から、適切な作業を条件付きで実行するために、自分が内側にいるかどうか、または囲んでいるインスタンスが誰であるかを確認する方法がわかりません。誰もこれを行う方法を知っていますか?
どうもありがとう!