Получить имя абстрактного типа
Я пытаюсь создать черту, которая будет предоставлять имя абстрактного типа, который добавляется в подкласс:
trait T {
type T
def myClassOf[T:ClassTag] = implicitly[ClassTag[T]].runtimeClass
def getType = {
myClassOf[T].getSimpleName
}
}
class TT extends T {
type T = String
}
Тем не менее, это не в состоянии скомпилировать:
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
^
Но это нормально работает, если я переместить getType
метод для подкласса. Может кто-нибудь объяснить, почему и есть ли способ сделать этот вызов из подкласса?
2 ответа
В тот момент, когда вы звоните myClassOf[T]
T
все еще абстрактный, поэтому компилятор не может сгенерировать ClassTag
для этого. Вы можете исправить это, задержав генерацию ClassTag[T]
до тех пор T
известен.
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
}
Если по какой-то причине добавить неявный параметр невозможно, я думаю, что лучший способ, возможно, - это какой-то метод. getClassT
быть реализованным в подклассах. Так как его тип возврата Class[T]
трудно обеспечить неправильную реализацию в подклассе.
trait Trait {
type T
def getType = {
getClassT.getSimpleName
}
def getClassT: Class[T]
}
class Sub extends Trait {
type T = String
def getClassT = classOf[T]
}
Обратите внимание, что приведенные выше ответы, хотя и хорошие, устарели с версии scala 2.10. предпочтительный метод теперь должен использовать TypeTag или ClassTag.
как описано в документации (см. ниже), теперь вы можете использовать их в неявных списках параметров или в контексте контекста, чтобы делать такие вещи:-
import scala.reflect.runtime.universe._
def paramInfo[T: TypeTag](x: T): Unit = {
val targs = typeOf[T] match { case TypeRef(_, _, args) => args }
println(s"type of $x has type arguments $targs")
}
scala> paramInfo(42)
type of 42 has type arguments List()
scala> paramInfo(List(1, 2))
type of List(1, 2) has type arguments List(Int)
смотрите scala документы на Typetags
см. API документы