5
votes

I need to define a val in my companion object which is initialized with a method which takes the companion class as parameter.

I want to handle this with traits to not repeat myself. My Problem ist, that X.getClass ist not the same as classOf[X]. The first is the class of the companion object and the second is the class of the companion class, but I need to get the companion class without hardcoding it directly.

Basically I need something like this:

trait Foo {

}

object FooCompanionObject[f <: Foo] {
    val fClazz = classOf[f]
}

// Bar's fClass should be classOf[Bar]
case class Bar extends Foo;

object Bar extends FooCompanionObject[Bar];

The problem is that I cannot get the class of an generic type due to type erasure

1
Why are you adding a generic type declaration to an object. Doesn't make any sense.cmbaxter
My object will have some methods that will return an f.user1563700

1 Answers

11
votes

There are several problems in your code. First, as you already said, the type will be erased, second objects (object FooCompanionObject[f <: Foo]) don't take type parameters and third, objects can not be extended (object Bar extends FooCompanionObject). To do what you want, you have to create an abstract base class for your companion objects, that takes a type parameter, which may be constrained to a specific type if you like, and has to be context bound on ClassTag. From the ClassTag you can then get the runtime class by calling runtimeClass on it. The final solution could look like this:

import scala.reflect.ClassTag
import scala.reflect.classTag

trait Foo

abstract class Companion[A <: Foo : ClassTag] {
  val fClazz = classTag[A].runtimeClass
}

class Bar extends Foo
object Bar extends Companion[Bar]


scala> Bar.fClazz
res2: Class[_] = class Bar