[英]Scala - obtaining a class object from a generic type
是否可以純粹從泛型參數創建一個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框架中的方法。
有什么指針嗎?
def myClassOf[T:ClassTag] = implicitly[ClassTag[T]].runtimeClass
您可以將m.erasure
的結果m.erasure
為Class[T]
:
class myclass[T] {
def something()(implicit m: Manifest[T]): Class[T] =
m.erasure.asInstanceOf[Class[T]]
}
這適用於基本(非泛型)類型:
scala> new myclass[String]().something()
res5: Class[String] = class java.lang.String
但是請注意如果我使用像List[String]
這樣的實例化類型構造函數來實現T
:
scala> new myclass[List[String]]().something()
res6: Class[List[String]] = class scala.collection.immutable.List
由於擦除,給定類型構造函數的所有可能實例化只有一個Class
對象。
我不確定為什么Manifest[T].erasure
返回Class[_]
而不是Class[T]
,但如果我不得不推測,我會說這是為了阻止你使用Class
上的方法來比較兩個用於相等的類或子類型關系,因為當使用實例化的泛型類型對Class
進行參數化時,這些方法會給出錯誤的答案。
例如,
scala> classOf[List[String]] == classOf[List[Int]]
res25: Boolean = true
scala> classOf[List[String]].isAssignableFrom(classOf[List[Int]])
res26: Boolean = true
這些結果可能會讓您感到驚訝和/或導致程序中出現錯誤。 你不應該以這種方式比較類,而應該通過傳遞Manifest
來比較它們,因為它們有更多的信息*:
scala> manifest[List[String]] == manifest[List[Int]]
res27: Boolean = false
scala> manifest[List[String]] >:> manifest[List[Int]]
res28: Boolean = false
據我所知, Manifest
s意味着在大多數用例中取代Class
es ......當然,如果你使用的是一個需要Class
的框架,那就沒有多少選擇了。 我認為強制erasure
結果只是一種“承擔責任”,你使用的是劣質產品,風險自負:)
*請注意,正如Manifest的文檔所述 ,這些明顯的比較運算符“應僅被視為近似值,因為類型一致性的許多方面尚未在清單中充分表示。”
.erasure
為您提供類型擦除的類型。 如果您需要完整類型信息,則應返回Manifest
。
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]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.