1

与えられたev: Manifest[T]私はをClass[T]使用して取得することができますev.erasure.asInstanceOf[Class[T]]ev.erasure単独で静的タイプのを返すのは残念ですClass[_]

Class[T]キャストせずにマニフェストからを取得できますか?そうでない場合、祝福されたScalaクリエーターがメソッドで生のリターン型を選択した理由はありerasureますか?

これがほとんどのコードに与える影響はごくわずかであることを理解していますが、Scalaコードのほぼ非慣用的な部分でこの問題に遭遇し、何よりも興味があります。

4

3 に答える 3

4

消去された型を返す理由は、ほとんどの場合、実際に型が手元にManifestないジェネリックコードで使用されるためです。これにより、タイプが目的のタイプであるかどうかを実際にチェックすると誤って想定するのではなく、意図を明示的に宣言する必要があります。

もちろん、エンリッチマイライブラリパターンを使用して、タイプを保持する独自のメソッドを追加できます。

class ClassFriendlyManifester[T](m: Manifest[T]) {
  def toClass = m.erasure.asInstanceOf[Class[T]]
}
implicit def manifests_like_classes[T](m: Manifest[T]) = new ClassFriendlyManifester(m)

def example[T: Manifest] = implicitly[Manifest[T]].toClass

scala> example[String]
res2: Class[String] = class java.lang.String

def example2[T](implicit ev: Manifest[T]) = ev.toClass

scala> example2[String]
res5: Class[String] = class java.lang.String
于 2012-06-06T19:38:31.650 に答える
3

いいえ、キャストは自分で行う必要があります—そうする必要があります。Class返されたインスタンスで何をしたいかによっては、このキャストは潜在的に安全ではありません。自分のバージョンのキャストをロールインしたいとします。

def cast[T](obj: Any)(implicit m: Manifest[T]) =
  m.erasure.asInstanceOf[Class[T]].cast(obj)

これは危険です—チェックされていないことで示されますasInstanceOf。なんで?このコードはこのようなナンセンスで正常に実行されるため、たとえば次のようになります。

val listInt = List(1, 2, 3)
val listString = cast[List[String]](listInt)

そこで、List[Int]として入力しList[String]ます。そして、これはコンパイルされて正常に実行ClassCastExceptionされますが、コードの後半で予期しない行が発生する可能性があります。安全ではないため、Class[T]から直接取得できないのはそのためです。Manifest[T]

于 2012-06-06T21:42:12.523 に答える
1

Scalaの型システムは、の正しい型を与えるのに十分な表現力がありませんerasure。正しいタイプは、次のタイプと同様ですgetClass()

実際の結果タイプは次のとおりですClass<? extends |X|>|X| getClassが呼び出される式の静的型の消去です。

この場合、正しい型は次のようになると思いますClass[|X|]Manifest[T]型パラメーターが不変であるため)。これはとは異なりObject.getClass()ます。その場合、静的タイプとランタイムタイプが異なる可能性があるためです。

Number n = 0; 
Class<? extends Number> c = n.getClass();

ここで、の実行時タイプは、ではなく、にcなります。Class<Integer>Class<Number>

于 2012-06-06T21:49:38.310 に答える