0

第一次尝试使用 quasiquotes 来生成新的案例类:

val universe: scala.reflect.runtime.universe.type = scala.reflect.runtime.universe
import universe._
import scala.reflect.runtime.{currentMirror => m}
import scala.tools.reflect.ToolBox
val toolbox = m.mkToolBox()

trait Father
class A extends Father {
  println("I'm A")
  val a = 0
}
class B extends Father {
  println("I'm B")
  val b = 0
}

object Produce {
  def A(): A = {
    val weakT = weakTypeOf[A]
    val genTree = q"""
      case class Son() extends $weakT {
        println("I'm alive")
      }
      Son()
      """
    val compiledCode = toolbox.eval(genTree)
    compiledCode.asInstanceOf[A]
  }
  def apply[T <: Father](): T = {
    val weakT = weakTypeOf[T]
    val genTree = q"""
      case class Son() extends $weakT {
        println("I'm alive")
      }
      Son()
      """
    val compiledCode = toolbox.eval(genTree)
    compiledCode.asInstanceOf[T]
  }
}

Produce.A()

Produce[A]()

Produce.A() 的结果:

我是一个

我还活着

res0: A = 儿子()

Produce[A]() 的结果:

scala.tools.reflect.ToolBoxError:反射工具箱因未解析的自由类型变量而失败:T 在 :32:13 中由 apply 定义,您是否忘记对 reifee 外部的类型参数使用 TypeTag 注释?如果您在跟踪自由类型变量时遇到问题,请考虑在 scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$ToolBoxGlobal.verify(ToolBoxFactory.scala:82) 在 scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$ToolBoxGlobal 使用 -Xlog-free-types .compile(ToolBoxFactory.scala:208) at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$$anonfun$compile$2.apply(ToolBoxFactory.scala:429) at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$$anonfun$compile$2 scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$withCompilerApi$.liftedTree2$1(ToolBoxFactory.scala:355) 的 .apply(ToolBoxFactory.scala:422)。

4

1 回答 1

0

正如@Andreas Jim-Hartmann 所建议的那样,添加了':TypeTag'(请参阅下面的评论),现在此代码适用于通用和特定:

val universe: scala.reflect.runtime.universe.type = scala.reflect.runtime.universe
import universe._
import scala.reflect.runtime.{currentMirror => m}
import scala.tools.reflect.ToolBox
val toolbox = m.mkToolBox()

trait Father
class A extends Father {
  println("I'm A")
  val a = 0
}
class B extends Father {
  println("I'm B")
  val b = 0
}

object Produce {
  def A(): A = {
    val weakT = weakTypeOf[A]
    val genTree = q"""
      case class Son() extends $weakT {
        println("I'm alive")
      }
      Son()
      """
    val compiledCode = toolbox.eval(genTree)
    compiledCode.asInstanceOf[A]
  }
  def apply[T <: Father : TypeTag](): T = { //Fixed here
    val weakT = weakTypeOf[T]
    val genTree = q"""
      case class Son() extends $weakT {
        println("I'm alive")
      }
      Son()
      """
    val compiledCode = toolbox.eval(genTree)
    compiledCode.asInstanceOf[T]
  }
}

Produce.A()

Produce[A]()

Produce[B]()
于 2016-07-05T20:57:51.497 回答