Hello everyone, I’m trying to create a method to access the concrete type of type parameters of a class.
import scala.reflect.runtime.universe._
abstract class BaseClass
class A[T](a: T) extends BaseClass
class B[T, U](a: T, b: U) extends BaseClass
class C[T, U]() extends BaseClass
// Get the parametrics of a given instance x
def getConstructorParametrics[T](x: T)(implicit wtt: WeakTypeTag[T]): Seq[String] = {
wtt.tpe match {
case TypeRef(utype, usymbol, args) => args.map(_.toString.replaceAll(",(?! )", ", "))
}
}
This method works but only if I call it directly:
getConstructorParametrics(new A(1)) // List("Int")
getConstructorParametrics(new B(1, "hello")) // List("Int", "String")
getConstructorParametrics(new C[Int, String]) // List("Int", "String")
getConstructorParametrics(new C[Int, A[Int]]) // List("Int", "A[Int]")
In my use case, I have to call that function from a wrapper function. However, it returns an empty list:
def wrapperFn1[T <: BaseClass](x: T) = getConstructorParametrics(x)
wrapperFn1(new A(1)) // List()
wrapperFn1(new B(1, "hello")) // List()
wrapperFn1(new C[Int, String]) // List()
wrapperFn1(new C[Int, A[Int]]) // List()
I found that it works if I do something like this:
def wrapperFn2[T <: BaseClass](x: T)(implicit wtt: WeakTypeTag[T]) = getConstructorParametrics(x)(wtt)
But I cannot, in my case, the wrapper function signature is already defined and I can’t really update it. I also tried to use TypeTag
but it returns the type parameter symbol rather than the concrete type. Namely, List(T), List(T, U), List(T, U), List(T, U)
for the cases above.
Does anyone have suggestions for doing that?
This is the scastie template: Scastie - An interactive playground for Scala.