2015-01-06 2 views
2

Я знаю, что TypeToken гуавы является способен это:Получить содержащий общие типы с ClassTag

class C[I, O]  

class A[T] { 
    val tok = new TypeToken[T](getClass){} 
} 

val a = new A[C[Integer, String]]{} 
println(a.tok) // somepackage.C<java.lang.Integer, java.lang.String> 

Но с ClassTag SCALA, я получаю:

class B[T: ClassTag] { 
    // runtime class 
    val clazz = implicitly[ClassTag[T]].runtimeClass 
    // also tries to construct a guava type token 
    val tok = TypeToken.of(clazz).asInstanceOf[TypeToken[T]] 
} 

val b = new B[C[Integer, String]] 
println(b.clazz) // class somepackage.C 
println(b.tok) // somepackage.C 

Так с ClassTag, генетические типы содержащихся C теряются. Возможно ли получить некоторый пакет.C с ClassTag или другими вещами в scala?

Спасибо!

ответ

1

TypeToken делает интересный трюк. Скажем, у вас есть это:

class A[T] 
class B extends A[String] 

Хотя Java стирает параметры типа во время выполнения, суперкласс B не A[T], но A[String]. Эта информация сохраняется и может быть получена. Так что, когда вы это делаете:

val tok = new TypeToken[T](getClass){} 

{} в конце означает, что вы создаете анонимный подкласс из TypeToken, тот, который вложен на A[T], так что каждый экземпляр A[T] будет на самом деле привести к другой анонимный подкласс.

В любом случае, это основная идея, и это зависит от анонимных подклассов, вложенных в параметризованный класс. Просто наличие ClassTag (который в основном представляет собой обертку вокруг Class) недостаточно.

Scala может сохранить полный тип информации, используя TypeTag, но это связано с затратами. Система типа Scala довольно сложна, намного сложнее, чем Java, и поэтому сохранение полной информации о типе требует большого количества кода.

Таким образом, в то время как ClassTag, которая в основном зависит от Java-й в комплекте Class, поставляется с scala-library, чтобы использовать TypeTag вам нужно добавить scala-reflect ваши зависимости, что составляет около 4.2MB на Scala 2.11.4.

После того, как вы есть, что, однако, остальное тривиально, как показано на lmm (бесстыдной копия & пасты из его answer):

import scala.reflect.runtime.universe._ 

class C[I, O] 

class A[T: TypeTag] { 
    val tpe = typeOf[T] 
} 

val a = new A[C[Integer, String]] 
println(a.tpe) // C[java.lang.Integer,String] 
+0

Спасибо за объяснение. Но можем ли мы создать java.lang.reflect.Type из TypeTag? – darkjh

+0

@ darkjh Я так не думаю. –

3

Я думаю, что вы хотите TypeTag и typeOf

import scala.reflect.runtime.universe._ 

class C[I, O] 

class A[T: TypeTag] { 
    val tpe = typeOf[T] 
} 

val a = new A[C[Integer, String]] 
println(a.tpe) // C[java.lang.Integer,String] 
+0

Fantastic! Спасибо за это. – Malcolm

Смежные вопросы