问题
When reflecting the foo()
method of the class Cls
we can easily get the concrete return type using the following.
class Cls {
def foo() =
List("A", "B")
}
val classType = ru.typeOf[Cls]
val classMirror = toolbox.mirror.reflectClass(classType.typeSymbol.asClass)
val ctorSymbol = classType.decl(ru.termNames.CONSTRUCTOR).asMethod
val methodSymb = classType.decl(ru.TermName("foo")).asMethod
val ctor = classMirror.reflectConstructor(ctorSymbol)
val instance = ctor()
val im = toolbox.mirror.reflect(instance)
val foo = im.reflectMethod(methodSymb)
println(foo()) // List(A, B)
println(methodSymb.returnType) // List[String]
However, if we define the class Cls
at runtime via the toolbox and then use the same method reflection process, we will only get the abstract return type (List
) of the foo()
method.
import ru._
val tree =
q"""class Cls {
def foo() =
List("A", "B")
}""".asInstanceOf[ru.ClassDef]
val classSymbol = toolbox.define(tree).asClass
val classType = classSymbol.selfType
val classMirror = toolbox.mirror.reflectClass(classType.typeSymbol.asClass)
val ctorSymbol = classType.decl(ru.termNames.CONSTRUCTOR).asMethod
val methodSymb = classType.decl(ru.TermName("foo")).asMethod
val ctor = classMirror.reflectConstructor(ctorSymbol)
val instance = ctor()
val im = toolbox.mirror.reflect(instance)
val foo = im.reflectMethod(methodSymb)
println(foo()) // List("A", "B")
println(methodSymb.returnType) // List
Why do these code snippets produce different results?
How can we reflect the concrete return type of the foo()
method if Cls
is defined at runtime using the toolbox?
回答1:
I guess the thing is in type erasure.
Try to replace
val classType = classSymbol.selfType
with
val classType = toolbox.eval(q"scala.reflect.runtime.universe.typeOf[$classSymbol]").asInstanceOf[ru.Type]
Then methodSymb.returnType
is List[String]
.
来源:https://stackoverflow.com/questions/64798525/how-to-reflect-concrete-return-types-for-methods-of-classes-defined-at-runtime-u