标量反射,获取超类的类型参数

时间:2018-09-25 08:56:30

标签: scala generics reflection scala-reflect

如何从子类中获取超类类型参数的具体类型?

假设我有一个通用的超类,一个中间类和一个子类,如下所示:

class SuperClass[A, B]
class IntClass[A] extends SuperClass[A, Int]
class MyClass extends SuperClass[String, Int]

我想要一个函数“ getTypeArgs”,该函数返回SuperClass的类型参数:

val superClassType = typeOf[SuperClass[_, _]]

val superClassOfStringInt = appliedType(superClassType.typeConstructor, typeOf[String], typeOf[Int])
getTypeArgs(superClassOfStringInt, superClassType)
// [TEST1] should return List(String, Int)

getTypeArgs(typeOf[MyClass], superClassType)
// [TEST2] should return List(String, Int)

val intClassOfLong = appliedType(typeOf[IntClass[_]].typeConstructor, typeOf[Long])
getTypeArgs(intClassOfLong, superClassType)
// [TEST3] should return List(Long, Int)

我已经尝试了解决方法In Scala Reflection, How to get generic type parameter of a concrete subclass?

def getTypeArgs(t: Type, fromType: Type): List[Type] = {
  internal
    .thisType(t.dealias.typeSymbol)
    .baseType(fromType.typeSymbol.asClass)
    .typeArgs
}

它适用于TEST2,但是TEST1返回List(A,B),而TEST3返回List(A,Int)。

我可以通过添加一个检查符号是否相等的测试来修复TEST1:

def getTypeArgs(t: Type, fromType: Type): List[Type] = {
  if (t.erasure.typeSymbol == fromType.typeSymbol)
    t.typeArgs
  else
    internal
      .thisType(t.dealias.typeSymbol)
      .baseType(fromType.typeSymbol.asClass)
      .typeArgs
}

我不知道如何使TEST3正常工作。

1 个答案:

答案 0 :(得分:0)

解决方案实际上非常简单:

def getTypeArgs(t: Type, fromType: Type): List[Type] = {
    t.baseType(fromType.typeSymbol).typeArgs
}

此功能通过了所有测试。