使用classManifest提供具有上限类型的Class对象

时间:2012-07-06 00:37:19

标签: scala generics manifest type-erasure

假设我需要提供一个带有java.lang.Class对象的方法,该对象表示某个父类A的子类。我需要从另一个方法执行此操作,该方法具有一个泛型参数,其上限类型绑定到A

我认为这可行:

class A
def f(clazz: java.lang.Class[_ <: A]) = ()
def g[T <: A : Manifest] = f(classManifest[T].erasure)

但事实并非如此:

<console>:9: error: type mismatch;
 found   : java.lang.Class[_$1(in method g)] where type _$1(in method g)
 required: java.lang.Class[_ <: A]
         def g[T <: A : Manifest] = f(classManifest[T].erasure)
                                                       ^

为什么编译器不能确定T确实是A的子类?无论如何我能帮忙吗?或者我应该以完全不同的方式处理这个问题?

1 个答案:

答案 0 :(得分:3)

它不起作用,因为erasure has the type Class[_],这是一种存在类型。这意味着Class对象erasure由某种类型进行参数化,但这与哪种确切类型并不重要。 erasure上面没有Class[T]类型。

方法f需要Class[_ <: A]类型的参数,该参数是已知的某种类型A的子类型。上限不一定由上面的Class[_]类型确保。

解决方案:您知道erasure具有正确的类型,只是此类型未在ClassManifest对象中公开。简单地投下它:

classManifest[T].erasure.asInstanceOf[Class[A]]

编辑:

如果您有B的子类A

scala> class A

scala> def f(clazz: java.lang.Class[_ <: A]) = ()

scala> def g[T <: A : Manifest] = f(classManifest[T].erasure.asInstanceOf[Class[A]])

scala> g[A]

scala> class B extends A

scala> g[B]