2016-12-02 184 views
2

獲取一般價值類參數類型我想一般價值類參數的真實Type。我想:通過反射

import scala.reflect.runtime.universe._ 

case class Test[T](value: T) extends AnyVal 

object Main extends App { 
    val tag = implicitly[TypeTag[Test[String]]] 
    val constructor = tag.tpe.members.collect { 
    case m: MethodSymbol if m.isPrimaryConstructor => m 
    }.headOption 
    val constructorParams = constructor.map(_.paramLists.flatten).collect { 
    case param :: Nil => param 
    } 
    constructorParams.map(_.typeSignature).foreach(println) 
} 

但它打印:

牛逼

我知道,我可以用類型參數:

tag.tpe.typeArgs.foreach(println) 

,輸出:

字符串

Test類可以定義這樣的:

case class Test[T](value: List[T]) extends AnyVal 

所以類型參數和參數類型的類型是不同的。

我該怎麼做?

回答

1

在編譯器中有一個名爲「從中可以看出」的操作,它返回與特定所有者類型有關的成員類型。

下面是在REPL會話的一個示例:

Welcome to Scala 2.12.0 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_102). 
Type in expressions for evaluation. Or try :help. 

scala> import scala.reflect.runtime.universe._ 
import scala.reflect.runtime.universe._ 

scala> case class Test[T](value: List[T]) extends AnyVal 
defined class Test 

scala> val tp = typeOf[Test[String]] 
tp: reflect.runtime.universe.Type = Test[String] 

scala> val cls = tp.typeSymbol 
cls: reflect.runtime.universe.Symbol = class Test 

scala> val constructor = tp.members.collect({case m: MethodSymbol if m.isPrimaryConstructor => m}).head 
constructor: reflect.runtime.universe.MethodSymbol = constructor Test 

scala> constructor.info.asSeenFrom(tp, cls).paramLists.head.head.info 
res0: reflect.runtime.universe.Type = scala.List[String] 

scala> // alternatively 

scala> constructor.infoIn(tp).paramLists.head.head.info 
res1: reflect.runtime.universe.Type = scala.List[String] 
+0

什麼'Symbol.info'和'Symbol.typeSignature'之間的區別? – mixel

+0

我認爲它們是一樣的,'info'是更多的編譯器內部俚語,而'typeSignature'可能是反射API作爲更好的名稱添加的。 –