Поиск параметров типа с помощью отражения в Scala 2.10?
Используя теги типа, я могу видеть параметры некоторого типа:
scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._
scala> typeOf[List[Int]]
res0: reflect.runtime.universe.Type = List[Int]
Но я просто не могу понять, как программным способом вывести это "Int" оттуда в общем виде.
(Я бродил в REPL в течение часа, пробуя перестановки в Type, чтобы посмотреть, что я могу получить из него... Я получаю много вещей, которые указывают, что это "Список", но удачи в поиске это "Int"! И я не хочу прибегать к анализу вывода toString()...)
Даниэль Собрал имеет превосходный (как обычно) краткий обзор, в котором он дразнящим образом приближается к тому, что я ищу, но (по-видимому), только если вы знаете, для этого конкретного класса, какой-то конкретный метод, тип которого может быть допрошены:
scala> res0.member(newTermName("head"))
res1: reflect.runtime.universe.Symbol = method head
scala> res1.typeSignatureIn(res0)
res2: reflect.runtime.universe.Type = => Int
Но я надеюсь на что-то более общее, не включающее рутирование в списке объявленных методов, и надеюсь, что один из них будет где-то захватывать (и, следовательно, разглашать) информацию о текущем типе тега.
Если Scala может так легко напечатать "List[Int]", с какой стати так трудно обнаружить эту часть "Int", не прибегая к сопоставлению строковых шаблонов? Или я просто что-то упускаю действительно, действительно очевидно?
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...
2 ответа
К сожалению, я не думаю, что есть метод, который даст вам параметры, но вы можете получить их следующим образом:
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
Редактировать Вот немного более приятный способ достичь того же (после обсуждения scala-internals):
scala> res0.asInstanceOf[TypeRefApi].args
res1: List[reflect.runtime.universe.Type] = List(Int)
Начиная с Scala 2.11
, вы можете просто использовать:
yourGenericType.typeArgs.head
Смотрите пункт изменений макроса № 14.