2

How can one let a superclass have access to its concrete instance's type?

class Base {
  val t = typeOf[this.type]
}

class X extends Base {
}

assert((new X).t =:= typeOf[X]) <-- fails!!!

So, the idea is that Base.t should reflect the concrete type of the instance...

user3612643
  • 5,096
  • 7
  • 34
  • 55
  • I can't test because my IDE's playing up, but can't you have an overridden method in each child class that returns the child class's own type? Then inheritance means the superclass will get the right type when it calls that method – The Archetypal Paul Sep 08 '15 at 10:15
  • Did you find an answer yet? Java has a method getClass to return Class but Scala doesn't have a method to return Type – SwiftMango Aug 03 '18 at 20:32

2 Answers2

2

It's unfortunately a common misunderstanding of this.type: it isn't the class of the instance, it's the singleton type (i.e. the type which only has one member: this). It won't work without inheritance either.

This can be done using F-bounded polymorphism:

class Base[A <: Base[A] : TypeTag] {
  val t = typeOf[A]
}

class X extends Base[X]
Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487
  • This only works for one level. Assuming you now have a class Y extending X, it's not possible to inject Y into Base[Y]. – user3612643 Sep 09 '15 at 13:00
  • Yes. Unfortunately, to work around it, you have to make `Base` a trait, and since `: TypeTag` is a shorthand for a constructor argument, it'll have to become a field and be set explicitly in each subtype. This looks worse to me than just adding `override val t = typeOf[Y]` to `Y`, depending on how many such classes you have (you may want to make `t` a `lazy val` to avoid issues with initialization order). – Alexey Romanov Sep 09 '15 at 19:29
0

How about making t a method and making that generic.

  import scala.reflect.runtime.universe._
  class Base {
    def myActualType[T <: Base](b: T)(implicit tt: TypeTag[T]) = typeOf[T]
  }
  class Foo extends Base 
  class Bar extends Foo 
  val bar = new Bar
  assert(bar.myActualType(bar) =:= typeOf[Bar])

The downside is that you always have to send the object reference to it when you call it, but you get what you want.

Mahdi
  • 1,778
  • 1
  • 21
  • 35