¿Encontrar parámetros de tipo a través de la reflexión en Scala 2.10?
reflection scala-2.10 (2)
Usando etiquetas de tipo, puedo ver los parámetros de algún tipo:
scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._
scala> typeOf[List[Int]]
res0: reflect.runtime.universe.Type = List[Int]
Pero simplemente no puedo entender cómo sacar ese "Int" programáticamente de allí, de una manera general.
(Estuve dando vueltas en REPL durante una hora, probando permutaciones en Type, para ver qué puedo obtener de él ... Recibo muchas cosas que indican que se trata de una "Lista", pero buena suerte para encontrar ese "Int"! Y realmente no quiero recurrir a analizar el resultado de toString () ...)
Daniel Sobral tiene una excelente visión general (como de costumbre) here , en la que se acerca tentadoramente a lo que estoy buscando, pero (aparentemente) solo si usted sabe, para esa clase en particular, algún método específico cuyo tipo puede ser interrogado:
scala> res0.member(newTermName("head"))
res1: reflect.runtime.universe.Symbol = method head
scala> res1.typeSignatureIn(res0)
res2: reflect.runtime.universe.Type = => Int
Pero espero algo más general, que no implique rastrear la lista de métodos declarados y esperar que uno de ellos capture (y divulgue) la información del tipo actual de la etiqueta en alguna parte.
Si Scala puede imprimir tan fácilmente "List [Int]", ¿por qué es tan difícil descubrir esa parte "Int" de eso, sin recurrir a la coincidencia de patrones de cadenas? ¿O simplemente me estoy perdiendo algo realmente obvio?
scala> res0.typeSymbol.asInstanceOf[ClassSymbol].typeParams
res12: List[reflect.runtime.universe.Symbol] = List(type A)
scala> res12.head.typeSignatureIn(res0)
res13: reflect.runtime.universe.Type =
Grr ...
Comenzando con Scala 2.11
, simplemente puede usar:
yourGenericType.typeArgs.head
Consulte el número de registro de cambios de macros número 14.
Tristemente, no creo que haya un método que le proporcione los parámetros, pero puede obtenerlos de esta manera:
Welcome to Scala version 2.10.0-20121007-145615-65a321c63e (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_35).
Type in expressions to have them evaluated.
Type :help for more information.
scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._
scala> typeOf[List[Int]]
res0: reflect.runtime.universe.Type = scala.List[Int]
scala> res0 match { case TypeRef(_, _, args) => args }
res1: List[reflect.runtime.universe.Type] = List(Int)
scala> res1.head
res2: reflect.runtime.universe.Type = Int
Editar Aquí hay una forma un poco más agradable de lograr lo mismo (siguiendo una discusión sobre scala-internals ):
scala> res0.asInstanceOf[TypeRefApi].args
res1: List[reflect.runtime.universe.Type] = List(Int)