1

Suppose I have an object that extends some abstract class

case class Id[T] private(v: String)

object SomeObj extends SomeAbstractClass[SomeCaseClass, AnotherObj.type, Id[SomeCaseClass]]

Would it be possible to get the following type parameters from SomeObj at runtime?

  • SomeCaseClass
  • AnotherObj.type
  • Id[SomeCaseClass]
Andrey Tyukin
  • 43,673
  • 4
  • 57
  • 93
d-_-b
  • 4,142
  • 6
  • 28
  • 43

1 Answers1

3

Assuming these imports and definitions (for a self-contained example):

import scala.reflect.runtime.universe._
trait Foo[A, B, C]
object Bar extends Foo[Int, String, Option[Short]]

Explicitly referring to Bar.type:

internal
  .thisType(typeOf[Bar.type].typeSymbol.asClass)
  .baseType(typeOf[Foo[_,_,_]].typeSymbol.asClass)
  .typeArgs

Without referring to Bar.type:

val a: Any = Bar // pretend that it's some instance, not necessarily `Bar`
val m = runtimeMirror(getClass.getClassLoader)
internal
  .thisType(m.reflect(a).symbol.asClass)
  .baseType(typeOf[Foo[_,_,_]].typeSymbol.asClass)
  .typeArgs

Both gives:

List(
  scala.Int,
  String,
  scala.Option[scala.Short]
)

Both solutions inspired by this answer here.

Andrey Tyukin
  • 43,673
  • 4
  • 57
  • 93
  • I'm wondering what type erasure actually mean now if we still can restore generic types at runtime .. – Bogdan Vakulenko Jun 06 '19 at 10:30
  • 2
    @BogdanVakulenko This works only if all type arguments are fixed during class/object definition. In case of singletons, it works because if there is only one instance of a given class, the type parameters can't vary at all, so it's just looking up constants. It doesn't help with finding whether an empty list was originally `List[Int]` or `List[String]`, because `List` is not a singleton. – Andrey Tyukin Jun 06 '19 at 10:45