2012-06-25 4 views

ответ

3

Вы не можете из-за типа erasure. Тем не менее, я бы сказал, что ваша попытка сделать это сформирована из неправильного понимания.

  • Точка системы типа предназначена для того, чтобы компилятор мог более разумно рассуждать о правильности вашей программы.
  • В системе статического типа, каждая ссылка имеет тип, который не может быть изменен

В вашей программе есть одна ссылка, a и тип этой ссылки является ClassWithTypeParameter[S]. Что. Является. Все. Компилятор может знать, что можно сделать с этой ссылкой. Типы существуют только для компилятора. Тот факт, что в время выполнения, a было присвоено значению, которое было ClassWithTypeParameter[A], не имеет значения.


Один из возможных способов сделать это в некотором приближении (ограничено стиранием) заключается в использовании проявляется (называется что-то еще в 2.10):

class ClassWithTypeParameter[+T: Manifest] { def erasure = manifest[T].erasure } 

Тогда вы можете позвонить erasure, который вы получите java.lang.Class назад. Как я уже сказал, это ограничено. класс это не то же самое, как типа и нет никакого способа отличить, например, ClassWithTypeParameter[List[Int]] от ClassWithTypeParameter[List[Double]]

+0

Но можно используйте манифесты, чтобы различать «CWTP [List [Int]]» и «CWTP [List [Double]]» - просто не удаляйте стирание. –

+0

@oxbow_lakes Спасибо за ваше объяснение, это очень помогло. –

2

Следующая плохая идея (как и большинство использования отражения), но она работает:

class ClassWithTypeParameter[+T: Manifest] { 
    def paramIs[V: Manifest] = manifest[T] == manifest[V] 
} 

Который дает нам:

scala> val a: ClassWithTypeParameter[S] = new ClassWithTypeParameter[A] 
a: ClassWithTypeParameter[S] = [email protected] 

scala> a.paramIs[A] 
res0: Boolean = true 

scala> a.paramIs[S] 
res1: Boolean = false 

scala> a.paramIs[B] 
res2: Boolean = false 

И:

scala> val i = new ClassWithTypeParameter[List[Int]] 
i: ClassWithTypeParameter[List[Int]] = [email protected] 

scala> i.paramIs[List[Int]] 
res3: Boolean = true 

scala> i.paramIs[List[Double]] 
res4: Boolean = false 

Вы могли бы написать подобные paramSubtypeOf и paramSupertypeOf методы с использованием Manifest «s <:< и >:>.

В Scala 2.10 (Milestone 4 или более поздней версии) есть a much more flexible way получить тип:

class ClassWithTypeParameter[+T: TypeTag] { 
    def paramType = reflect.runtime.universe.typeTag[T].tpe 
} 

Теперь вы могли бы написать такие вещи, как a.paramType.parents, чтобы получить немедленные супертипы и т.д.

+0

Благодарим вас за дополнительную информацию! –

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