2016-12-02 6 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) 
} 

をそれが印刷されます:私が試した

をT

私は私が型引数を得ることができることを知っている:

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と共に追加されました。 –

関連する問題