Scala“反射工具箱由于未解决的自由类型而失败”

时间:2016-07-05 14:11:09

标签: scala scala-quasiquotes

第一次尝试使用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   你有没有忘记使用TypeTag注释作为reifee外部的类型参数?   如果您在跟踪自由类型变量时遇到麻烦,请考虑使用-Xlog-free-types     在scala.tools.reflect.ToolBoxFactory $ ToolBoxImpl $ ToolBoxGlobal.verify(ToolBoxFactory.scala:82)     在scala.tools.reflect.ToolBoxFactory $ ToolBoxImpl $ ToolBoxGlobal.compile(ToolBoxFactory.scala:208)     在scala.tools.reflect.ToolBoxFactory $ ToolBoxImpl $$ anonfun $ compile $ 2.apply(ToolBoxFactory.scala:429)     在scala.tools.reflect.ToolBoxFactory $ ToolBoxImpl $$ anonfun $ compile $ 2.apply(ToolBoxFactory.scala:422)     at scala.tools.reflect.ToolBoxFactory $ ToolBoxImpl $ withCompilerApi $ .liftedTree2 $ 1(ToolBoxFactory.scala:355)     在scala.tools.reflect.ToolBoxFactory $ ToolBoxImpl $ withCompilerApi $ .apply(ToolBoxFactory.scala:355)     在scala.tools.reflect.ToolBoxFactory $ ToolBoxImpl.compile(ToolBoxFactory.scala:422)     在scala.tools.reflect.ToolBoxFactory $ ToolBoxImpl.eval(ToolBoxFactory.scala:444)     在Produce $ .apply(:40)     ... 34岁以上

1 个答案:

答案 0 :(得分:0)

根据@Andreas Jim-Hartmann的建议,补充说&#39; :TypeTag&#39; (见下面的评论)现在这段代码适用于通用和特定的:

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]()