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

发布于 2024-12-08 04:41:32 字数 1052 浏览 0 评论 0原文

基本上,我想要一个按类型对象索引的 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 方法并将该类作为参数传递给 存在。有更好的办法吗?

Basically, I want to have a Map indexed by type objects. In this case, I'm trying to use Class as the "type type".

the following code:

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

does not compile, because (1) classOf[T] is apparently invalid:

error: class type required but T found

and (2) item.getClass is of the wrong type:

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

I see two ways to accomplish this:
either drop the type requirement and use Class[_] only
or use Manifest instead of Class (not sure how to do that yet, any examples are welcome)

But more generally, why is classOf[T] invalid, and how do I obtain a class object for a parametrized type?

update: I found out that I can use item.getClass.asInstanceOf[Class[T]] to get to the class object. For one, this is ugly. For two, it doesn't help much, because later in the code i have functions such as this one:

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

Obviously, I could use the asInstanceOf method in insertItem and pass the class as a parameter to isPresent. Is there a better way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

向日葵 2024-12-15 04:41:32

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

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)

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

You can use manifests to achieve this:

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)

You are losing the types through erasure, so you need to add the implicit argument to the putThing which contains the name of the class, using a Manifest.

青柠芒果 2024-12-15 04:41:32

问题再次是泛型在运行时不可用。编译器会执行找出 T 是什么的任务,但它不能,因为它只能在运行时知道。

您可以使用清单来获取该信息: 什么是 Scala 中的清单以及何时需要它?

The problem is once again that generics aren't available at run time. The compiler does the task of figuring out what T is, but it can't because it is only know at run time.

You could use a manifest to obtain that information: What is a Manifest in Scala and when do you need it?.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文