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]
}