I'm trying to create a trait that would provide the name of the abstract type that is added in the sub-class:
trait T {
type T
def myClassOf[T:ClassTag] = implicitly[ClassTag[T]].runtimeClass
def getType = {
myClassOf[T].getSimpleName
}
}
class TT extends T {
type T = String
}
However, this fails to compile:
Error:(7, 15) not enough arguments for method myClassOf: (implicit evidence$1: scala.reflect.ClassTag[T.this.T])Class[_].
Unspecified value parameter evidence$1.
myClassOf[T].getSimpleName
^
But it works fine if I move the getType method to the sub-class. Can someone explain why and whether there is a way to do this call from the sub-class?
At the point where you call myClassOf[T] T is still abstract, so the compiler can not generate a ClassTag for it. You can fix it by delaying the generation of the ClassTag[T] until T is known.
trait Trait {
type T
def myClassOf[A:ClassTag] = implicitly[ClassTag[A]].runtimeClass
def getType(implicit tag: ClassTag[T]) = {
myClassOf[T].getSimpleName
}
}
class Sub extends Trait {
type T = String
}
If adding an implicit parameter is impossible for some reason I think the best way is probably requiring some method getClassT to be implemented in subclasses. Since its return type is Class[T] it's difficult to provide a wrong implementation in a subclass.
trait Trait {
type T
def getType = {
getClassT.getSimpleName
}
def getClassT: Class[T]
}
class Sub extends Trait {
type T = String
def getClassT = classOf[T]
}