通过Scala反射查找封闭的实例(如果有的话)
我试图使用Scala反射来定义特征案例类,并且它们的同伴可以实现成为“可导出”(例如,映射[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内部,我不知道如何检查我是内部还是我的封闭实例,以有条件地执行适当的工作。 有谁知道如何做到这一点?
非常感谢!
我在这里看到的主要问题是您在内部类的伴侣对象中使用反射。 Test2类将定义一个名为$ outer的字段,该字段包含外部类,但是,与Test2伴随对象相比,您无法获得需要创建Test2的Outer实例。 我可以看到的唯一工作就是将可选实例传递给你的伴侣特质:
trait CompanionOfReflectiveConstructable[T] {
def tType: Type
def outer: Option[AnyRef] = None
val mirror = runtimeMirror(this.getClass.getClassLoader)
val tClassMirror = outer
.map(a => mirror.reflect(a).reflectClass(tType.typeSymbol.asClass))
.getOrElse(mirror.reflectClass(tType.typeSymbol.asClass))
val ctorF = tClassMirror.reflectConstructor(tType.declaration(nme.CONSTRUCTOR).asMethod)
// 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
class Test1 extends ReflectiveConstructable
object Test1 extends CompanionOfReflectiveConstructable[Test1] {
def tType = typeOf[Test1]
}
class Outer {
object Test2 extends CompanionOfReflectiveConstructable[Test2] {
def tType = typeOf[Test2]
override def outer = Option(Outer.this)
}
class Test2 extends ReflectiveConstructable
}
如果有一种方法可以从Test2伴随对象中获得外部实例,那很好,但是遗憾的是它在运行时不可用。
链接地址: http://www.djcxy.com/p/76523.html上一篇: Finding enclosing instance (if any) by Scala reflection