如何确定Scala中类型参数的子类型?

时间:2012-06-25 21:58:36

标签: scala type-parameter

class S
class A extends S
class B extends S

class ClassWithTypeParameter[+T]

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

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

2 个答案:

答案 0 :(得分: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]]

答案 1 :(得分: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

您可以使用paramSubtypeOf的{​​{1}}和paramSupertypeOf撰写类似的Manifest<:<方法。

在Scala 2.10(里程碑4或更高版本)中,有a much more flexible way来获取类型:

>:>

现在你可以编写像class ClassWithTypeParameter[+T: TypeTag] { def paramType = reflect.runtime.universe.typeTag[T].tpe } 这样的东西来获得直接的超类型等等。