You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 09:53:16