Scala - 从泛型类型获取类对象
是否可以纯粹从泛型参数创建一个 Class 对象?例如:
class myclass[T] {
def something(): Class[_ <: T] =
classOf[T] //this doesn't work
}
由于类型将在运行时被删除,因此这似乎是清单的工作,但我还没有找到演示这种特殊用法的示例。我尝试了以下方法,但它也不起作用:
class myclass[T] {
def something()(implicit m: Manifest[T]): Class[_ <: T] =
m.erasure //this doesn't work
}
我怀疑此失败是由于,正如 API 指出的那样,m.erasure
结果的类型与T
。
编辑:我对 T
类型并不是很感兴趣,我只需要一个 Class[_ <: T]
类型的对象来传递给中的方法hadoop 框架。
有什么指点吗?
Is it possible to create a Class object purely from a generic parameter? For example:
class myclass[T] {
def something(): Class[_ <: T] =
classOf[T] //this doesn't work
}
Since the type will have been erased at runtime, it seems like this a job for manifests, but I haven't found an example that demonstrates this particular usage. I tried the following, but it doesn't work either:
class myclass[T] {
def something()(implicit m: Manifest[T]): Class[_ <: T] =
m.erasure //this doesn't work
}
I suspect this failure is due to, as the API points out, there is no subtype relationship between the type of m.erasure
's result and T
.
EDIT: I'm not really interested in what the type T
is, I just need an object of type Class[_ <: T]
to pass to a method in the hadoop framework.
Any pointers?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您可以将
m.erasure
的结果转换为Class[T]
:这对于基本(非泛型)类型效果很好:
但请注意,如果我使用实例化类型构造函数,例如
T
的List[String]
:由于擦除,对于给定的所有可能实例化,只有一个
Class
对象类型构造函数。编辑
我不确定为什么
Manifest[T].erasure
返回Class[_]
而不是Class[T]
,但如果我有推测,我想说这是为了阻止您使用Class
上的方法,这些方法允许您比较两个类的相等性或子类型关系,因为当类
使用实例化的泛型类型进行参数化。例如,
这些结果可能会让您感到惊讶和/或导致您的程序出现错误。您通常应该传递
Manifest
并比较它们,而不是以这种方式比较类,因为它们有更多信息*:据我了解,
Manifest
的意思是在大多数用例中取代Class
...但是,当然,如果您使用的框架需要Class
,则没有太多选择。我认为强行强制删除擦除
的结果只是一种“责任确认”,您使用的是劣质产品,风险由您自己承担:)*请注意,作为< a href="http://www.scala-lang.org/api/current/scala/reflect/Manifest.html" rel="nofollow noreferrer">Manifest 文档 说,这些清单比较运算符“应该被考虑只是近似值,因为类型一致性的许多方面尚未在清单中充分体现。”
You can cast the result of
m.erasure
to aClass[T]
:This works fine for basic (non-generic) types:
But note what happens if I use an instantiated type constructor like
List[String]
forT
:Due to erasure, there is only one
Class
object for all the possible instantiations of a given type constructor.Edit
I'm not sure why
Manifest[T].erasure
returnsClass[_]
instead ofClass[T]
, but if I had to speculate, I would say it's to discourage you from using the methods onClass
which allow you to compare two classes for equality or a subtype relationship, since those methods will give you wrong answers when theClass
is parameterized with an instantiated generic type.For example,
These results might surprise you and/or lead to a bug in your program. Instead of comparing classes this way, you should normally just pass around
Manifest
s instead and compare them, since they have more information*:As I understand it,
Manifest
s are meant to supersedeClass
es for most use cases... but of course, if you're using a framework that requires aClass
, there's not much choice. I would suppose that the imposition of casting the result oferasure
is just a sort of "acknowledgement of liability" that you're using an inferior product at your own risk :)* Note that, as the documentation for Manifest says, these manifest comparison operators "should be considered approximations only, as there are numerous aspects of type conformance which are not yet adequately represented in manifests."
.erasure
为您提供类型擦除到的类型。如果您想要完整的类型信息,您应该返回Manifest
。.erasure
gives you the type to which your type erases to. If you want a full type information, you should return theManifest
instead.