2016-07-05 33 views
0

試圖quasiquotes一般地產生新的情況下的類:Scala的首次 「反射工具箱失敗,原因是未解決的遊離型」

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()的結果:

I'm A

I'm alive

res0: A = Son()

爲產生結果[A]():

scala.tools.reflect.ToolBoxError: reflective toolbox failed due to unresolved free type variables: T defined by apply in :32:13 have you forgotten to use TypeTag annotations for type parameters external to a reifee? if you have troubles tracking free type variables, consider using -Xlog-free-types at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$ToolBoxGlobal.verify(ToolBoxFactory.scala:82) at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$ToolBoxGlobal.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.apply(ToolBoxFactory.scala:422) at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$withCompilerApi$.liftedTree2$1(ToolBoxFactory.scala:355) at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl$withCompilerApi$.apply(ToolBoxFactory.scala:355) at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl.compile(ToolBoxFactory.scala:422) at scala.tools.reflect.ToolBoxFactory$ToolBoxImpl.eval(ToolBoxFactory.scala:444) at Produce$.apply(:40) ... 34 elided

+0

你試過嗎? 'def apply [T <:父:TypeTag]():T = {' – devkat

+0

好!謝謝! –

回答

0

如所建議的通過@Andreas吉姆 - 哈特曼,增加 ':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]()