gpt4 book ai didi

scala - 在 Scala 反射中,如何获取具体子类的泛型类型参数?

转载 作者:行者123 更新时间:2023-12-04 11:02:44 25 4
gpt4 key购买 nike

假设我有一个通用父类(super class):

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

也产量 T ,并且无法通过 asSeenFrom 进行更正,因为以下代码不会更改结果:
member.returnType.asSeenFrom(baseType.tpe, baseType.tpe.typeSymbol.asClass)

最佳答案

我可以建议两种方法:

1) 从基类显示泛型类型:

import scala.reflect.runtime.universe._

class GenericExample[T: TypeTag](a: String, b: T) {
def fn(i: T) = "" + b + i
}

case class Example(a: String, b: Int) extends GenericExample[Int](a, b) {}

val classType = typeOf[Example].typeSymbol.asClass
val baseClassType = typeOf[GenericExample[_]].typeSymbol.asClass
val baseType = internal.thisType(classType).baseType(baseClassType)

baseType.typeArgs.head // returns reflect.runtime.universe.Type = scala.Int

2)添加返回类型的隐式方法:
import scala.reflect.runtime.universe._

class GenericExample[T](a: String, b: T) {
def fn(i: T) = "" + b + i
}

case class Example(a: String, b: Int) extends GenericExample[Int](a, b)

implicit class TypeDetector[T: TypeTag](related: GenericExample[T]) {
def getType(): Type = {
typeOf[T]
}
}

new Example("", 1).getType() // returns reflect.runtime.universe.Type = Int

关于scala - 在 Scala 反射中,如何获取具体子类的泛型类型参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38174763/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com