Scala反射运行时编译:类内引用实例化问题及动态类场景
解决方案
场景1:Example2是已存在的编译类
你遇到的问题核心是:tq"namespace.to.Example2"生成的是类型树(TypeTree),仅能用于类型标注(比如方法返回值),但实例化case class需要调用它的伴生对象apply方法,直接用类型树会触发“class is not a value”错误。
解决方法是获取Example2的伴生对象符号,在quasiquote中引用该符号来调用apply:
import scala.reflect.runtime import scala.reflect.runtime.universe import scala.reflect.runtime.universe._ import scala.tools.reflect.ToolBox object Stuff { val rm: universe.Mirror = runtime.currentMirror val tb: ToolBox[universe.type] = rm.mkToolBox() // 获取Example1的类型树(用于继承) val Example1 = tq"namespace.to.Example1" // 获取Example2的类符号 val example2ClassSym = rm.staticClass("namespace.to.Example2") // Example2的类型树(用于返回类型标注) val Example2 = tq"namespace.to.Example2" // 获取Example2的伴生对象符号 val example2CompanionSym = example2ClassSym.companion.asModule val classDef = tb .define( q""" case class MyClass extends $Example1 { def doWork(): $Example2 = { ${example2CompanionSym}("hello") // 调用伴生对象的apply方法 } } """.asInstanceOf[ClassDef] ).asClass }
原理:Scala中Example2("hello")本质是调用伴生对象的apply方法,直接引用伴生对象符号就能在反射编译时生成正确的调用代码。
场景2:Example2也是运行时编译的类
这种情况需要先编译并定义Example2,再获取它的类和伴生对象符号,用于后续定义MyClass:
import scala.reflect.runtime import scala.reflect.runtime.universe import scala.reflect.runtime.universe._ import scala.tools.reflect.ToolBox object Stuff { val rm: universe.Mirror = runtime.currentMirror val tb: ToolBox[universe.type] = rm.mkToolBox() // 1. 先编译并定义Example2类 val example2Def = q""" case class Example2(member: String) { def aMethod(): Example2 = this } """.asInstanceOf[ClassDef] val example2ClassSym = tb.define(example2Def).asClass // 2. 从类符号生成类型树(用于返回类型) val Example2 = example2ClassSym.toTypeTree // 获取Example2的伴生对象符号(用于实例化) val example2CompanionSym = example2ClassSym.companion.asModule // 3. 定义依赖Example2的MyClass val classDef = tb .define( q""" case class MyClass { def doWork(): $Example2 = { val ex = ${example2CompanionSym}("hello") ex.aMethod() } } """.asInstanceOf[ClassDef] ).asClass }
可选方案:如果你想用new关键字实例化,直接引用Example2的类符号即可:
val ex = new ${example2ClassSym}("hello")
内容的提问来源于stack exchange,提问作者stackoverflowflowflwofjlw
相关产品推荐
相关产品推荐

