mardi 25 septembre 2018

scala reflection, get type parameter of super class

How can I get the concrete type of a super class type parameters from a subclass?

Assuming that I have a generic super class, an intermediate class and a subclass as follow:

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

I'd like a function "getTypeArgs" that returns type parameters of 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)

I've tried the solution 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
}

It works for TEST2, but TEST1 returns List(A, B) and TEST2 returns List(A, Int).

I can fix the TEST1 by adding a test to check equality of symbols:

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
}

I don't know how to make TEST2 work.





Aucun commentaire:

Enregistrer un commentaire