简体   繁体   English

通过Scala 2.10中的反射查找类型参数?

[英]Finding type parameters via reflection in Scala 2.10?

Using type tags, I'm able to see the parameters of some type: 使用类型标签,我能够看到某些类型的参数:

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

scala> typeOf[List[Int]]
res0: reflect.runtime.universe.Type = List[Int]

But I just can't quite figure out how to programmatically get that "Int" out of there, in a general way. 但是我只是无法弄清楚如何以一般方式以编程方式从那里获取“Int”。

(I've been wandering around in REPL for an hour now, trying permutations on Type, to see what I can obtain from it... I get a lot of things which indicate this is a "List", but good luck on finding that "Int"! And I don't really want to resort to parsing the toString() output...) (我已经在REPL中闲逛了一个小时,在Type上尝试排列,看看我能从中得到什么......我得到了很多东西,表明这是一个“列表”,但是找到了好运“Int”!我真的不想解析toString()输出......)

Daniel Sobral has an excellent (as usual) quick overview here , in which he gets tantalizingly close to what I'm looking for, but (apparently) only if you happen to know, for that particular class, some specific method whose type can be interrogated: 丹尼尔·索布拉尔(Daniel Sobral) 在这里有一个很好的(通常)快速概述,其中他非常接近我正在寻找的东西,但(显然)只有你碰巧知道,对于那个特定的类,一些特定的方法,其类型可以是询问:

scala> res0.member(newTermName("head"))
res1: reflect.runtime.universe.Symbol = method head

scala> res1.typeSignatureIn(res0)
res2: reflect.runtime.universe.Type = => Int

But I'm hoping for something more general, which doesn't involve rooting around in the list of declared methods and hoping that one of them will capture (and thus divulge) the tag's current type information somewhere. 但是我希望有一些更通用的东西,它不涉及在声明的方法列表中生根,并希望其中一个将捕获(并因此泄露)标签的当前类型信息。

If Scala can so easily print "List[Int]", why on earth is it so hard to discover that "Int" part of that -- without resorting to string pattern matching? 如果Scala可以如此轻松地打印 “List [Int]”,那么为什么它很难发现“Int”的一部分 - 没有求助于字符串模式匹配? Or am I just missing something really, really obvious? 或者我只是遗漏了一些非常非常明显的东西?

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... 格儿...

Starting with Scala 2.11 , you can simply use: Scala 2.11开始,您可以简单地使用:

yourGenericType.typeArgs.head

See the macros changelog point number 14. 请参阅宏更改日志点编号14。

Sadly, I don't think that there's a method that will give you the parameters, but you can get hold of them this way: 可悲的是,我不认为有一种方法可以为您提供参数,但您可以通过这种方式获取它们:

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

Edit Here's a slightly nicer way to achieve the same thing (following a discussion on scala-internals ): 编辑这是一个更好的方法来实现相同的事情(在讨论scala-internals之后 ):

scala> res0.asInstanceOf[TypeRefApi].args
res1: List[reflect.runtime.universe.Type] = List(Int)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM