2
class S
class A extends S
class B extends S

class ClassWithTypeParameter[+T]

val a: ClassWithTypeParameter[S] = new ClassWithTypeParameter[A]

如何确定用于值 a 的类型参数的子类的类型?

4

2 回答 2

3

你不能因为类型擦除。但是,我认为您这样做的尝试是由于误解造成的。

  • 类型系统的意义在于,编译器可以更有力地推断程序的正确性。
  • 在静态类型系统中,每个引用都有一个无法更改的类型

在你的程序中,有一个引用,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]]

于 2012-06-25T23:02:56.253 回答
2

以下是一个坏主意(就像反射的大多数用途一样),但它有效:

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

这给了我们:

scala> val a: ClassWithTypeParameter[S] = new ClassWithTypeParameter[A]
a: ClassWithTypeParameter[S] = ClassWithTypeParameter@6493c09c

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]] = ClassWithTypeParameter@260702ee

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

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

您可以使用' sparamSubtypeOf和.paramSupertypeOfManifest<:<>:>

在 Scala 2.10(里程碑 4 或更高版本)中,有一种更灵活的方式来获取类型:

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

现在您可以编写诸如a.paramType.parents获取直接超类型之类的东西。

于 2012-06-25T23:37:56.920 回答