Generics Scala-从泛型类型获取类对象
是否可以纯粹从泛型参数创建类对象?例如:Generics Scala-从泛型类型获取类对象,generics,scala,manifest,Generics,Scala,Manifest,是否可以纯粹从泛型参数创建类对象?例如: class myclass[T] { def something(): Class[_ <: T] = classOf[T] //this doesn't work } classmyclass[T]{ def something():Class[\up>.erasure为您提供类型擦除到的类型。如果您需要完整的类型信息,则应返回清单 scala> class MyClass[A] { | def stuff(
class myclass[T] {
def something(): Class[_ <: T] =
classOf[T] //this doesn't work
}
classmyclass[T]{
def something():Class[\up>.erasure
为您提供类型擦除到的类型。如果您需要完整的类型信息,则应返回清单
scala> class MyClass[A] {
| def stuff(implicit m: Manifest[A]): Class[_] = m.erasure
| }
defined class MyClass
scala> new MyClass[Int].stuff
res551: java.lang.Class[_] = int
scala> new MyClass[List[Int]].stuff
res552: java.lang.Class[_] = class scala.collection.immutable.List
scala> class MyClass[A] {
| def stuff(implicit m: Manifest[A]): Manifest[A] = m
| }
defined class MyClass
scala> new MyClass[Int].stuff
res553: Manifest[Int] = Int
scala> new MyClass[List[Int]].stuff
res554: Manifest[List[Int]] = scala.collection.immutable.List[Int]
您可以将m.erasure
的结果强制转换为类[T]
:
class myclass[T] {
def something()(implicit m: Manifest[T]): Class[T] =
m.erasure.asInstanceOf[Class[T]]
}
这适用于基本(非泛型)类型:
但是请注意,如果我为T
使用像List[String]
这样的实例化类型构造函数,会发生什么:
scala> new myclass[List[String]]().something()
res6: Class[List[String]] = class scala.collection.immutable.List
由于擦除,对于给定类型构造函数的所有可能实例化,只有一个类
对象
编辑
我不知道为什么Manifest[T]。擦除返回Class[\u]
而不是Class[T]
,但如果我不得不推测,我会说这是为了阻止您使用类
上的方法,这些方法允许您比较两个类的相等性或子类型关系,因为当类
被实例化泛型类型参数化时,这些方法会给出错误的答案
比如说,
scala> classOf[List[String]] == classOf[List[Int]]
res25: Boolean = true
scala> classOf[List[String]].isAssignableFrom(classOf[List[Int]])
res26: Boolean = true
这些结果可能会让您大吃一惊和/或导致程序中出现错误。您通常不应该以这种方式比较类,而应该传递Manifest
s来比较它们,因为它们有更多信息*:
scala> manifest[List[String]] == manifest[List[Int]]
res27: Boolean = false
scala> manifest[List[String]] >:> manifest[List[Int]]
res28: Boolean = false
据我所知,Manifest
s在大多数用例中都意味着取代类
es……但当然,如果您使用的框架需要类
,那么没有太多选择。我想强制执行擦除
的结果只是一种“责任确认”您使用劣质产品的风险由您自己承担:)
*请注意,正如上面所说,这些清单比较运算符“应仅被视为近似值,因为清单中还没有充分表示类型一致性的许多方面。”因此,如果我需要一个实际的类[\uu]调用,该怎么办?scala为什么不只是生成类[t]
擦除的返回类型
?在编译过程中似乎可以保证这一点。@dhg我认为擦除并没有给你一个参数化的类
,因为根据定义它是“一个代表将被擦除的U类型的类”。类的擦除不包含其参数。但我不确定为什么没有其他方法返回参数化类。这可能是来自Java的class
类的一些限制。例如,List(1,2,3)。getClass
返回一个class[\uu]
@pelotom感谢您的大力响应。您的分析实际上非常有趣,而且非常有意义。与其他scala用户一样,我避免使用强制转换,因为这通常意味着您做错了什么。正如您所指出的,如果不是与外部框架(如d“责任确认”似乎很恰当。这个答案是为Scala 2.10和更高版本准备的,因为清单已被弃用。它在Scala 2.12中返回一个Class[\u]
,而“runtimeClass”上的文档说“注意,T
和[the”]之间没有子类型关系。”你知道如何实际获得Class[T]
?@Rich,您可以使用.asinstanteof[Class[T]
来转换类[\u]
运行时类,这似乎是可行的,谢谢。文档建议,在某些情况下,这将不起作用,尽管……“T和[That]之间没有子类型关系”。我现在想不出一个例子。
scala> classOf[List[String]] == classOf[List[Int]]
res25: Boolean = true
scala> classOf[List[String]].isAssignableFrom(classOf[List[Int]])
res26: Boolean = true
scala> manifest[List[String]] == manifest[List[Int]]
res27: Boolean = false
scala> manifest[List[String]] >:> manifest[List[Int]]
res28: Boolean = false
def myClassOf[T:ClassTag] = implicitly[ClassTag[T]].runtimeClass