假设我有一个通用超类:
class GenericExample[T](
a: String,
b: T
) {
def fn(i: T): T = b
}
和一个具体的子类:
case class Example(
a: String,
b: Int
) extends GenericExample[Int](a, b)
我想通过scala反射获取函数“fn”的类型参数,所以我选择并过滤它的成员:
import ScalaReflection.universe._
val baseType = typeTag[Example]
val member = baseType
.tpe
.member(methodName: TermName)
.asTerm
.alternatives
.map(_.asMethod)
.head
val paramss = member.paramss
val actualTypess: List[List[Type]] = paramss.map {
params =>
params.map {
param =>
param.typeSignature
}
}
我期待 scala 给我正确的结果,也就是说List(List(Int))
,我只得到了通用的List(List(T))
仔细研究文档,我发现 typeSignature 是罪魁祸首:
* This method always returns signatures in the most generic way possible, even if the underlying symbol is obtained from an
* instantiation of a generic type.
它建议我使用替代方案:
def typeSignatureIn(site: Type): Type
但是,由于类 Example 不再是通用的,我无法从 typeTag[Example] 获取站点,谁能建议我如何仅给定 typeTag[Example] 获取 typeOf[Int]?或者没有办法做到这一点,我必须恢复到 Java 反射?
非常感谢你的帮助。
更新:经过一些快速测试后,我发现即使MethodSymbol.returnType也无法按预期工作,以下代码:
member.returnType
也 yield T
,它不能被asSeenFrom纠正,因为下面的代码不会改变结果:
member.returnType.asSeenFrom(baseType.tpe, baseType.tpe.typeSymbol.asClass)