如何在Scala中创建类型对象的集合

时间:2011-10-02 23:12:00

标签: scala collections type-systems

基本上,我希望有一个由类型对象索引的Map。在这种情况下,我试图使用Class作为“类型类型”。

以下代码:

class SuperClass {}
val typemap = new HashMap[Class[_ <: SuperClass], SuperClass]

def insertItem1[T <: SuperClass] (item : T) = typemap += classOf[T] -> item
def insertItem2[T <: SuperClass] (item : T) = typemap += item.getClass -> item

不编译,因为(1)classOf [T]显然无效:

error: class type required but T found

和(2)item.getClass的类型错误:

Type mismatch, expected: Class[_ <: SuperClass], actual: Class[_]

我认为有两种方法可以做到这一点:
要么删除类型要求,只使用Class [_] 或使用Manifest而不是Class(不知道如何做到这一点,欢迎任何例子)

但更一般地说,为什么classOf [T]无效,如何获得参数化类型的类对象?

更新:我发现我可以使用item.getClass.asInstanceOf[Class[T]]来获取类对象。首先,这很难看。对于两个,它没有多大帮助,因为稍后在代码中我有这样的功能:

def isPresent[T <: SuperClass] = typemap contains classOf[T]

显然,我可以在insertItem中使用asInstanceOf方法,并将该类作为参数传递给isPresent。还有更好的方法吗?

2 个答案:

答案 0 :(得分:2)

您可以使用清单来实现此目的:

class TypeMap extends HashMap[Class[_], Any] {
    def putThing[T](t: T)(implicit m: Manifest[T]) = put(m.erasure, t)
}

val map = new TypeMap
map.putThing(4)
map.get(classOf[Int]) // returns Option[Any] = Some(4)

您正在通过擦除丢失类型,因此您需要使用Manifest将隐式参数添加到包含类名称的putThing中。

答案 1 :(得分:1)

问题再一次是泛型在运行时不可用。编译器负责确定T是什么,但它不能,因为它只在运行时知道。

您可以使用清单获取该信息:What is a Manifest in Scala and when do you need it?