Manifest
とTypeTag
にいくつか質問があります。私は、JVMがジェネリックスについて知らず、タイプを消去することを理解しています。だから私はManifest
を使用して、実行する種類の情報を転送することができ、このマニフェストはなぜ非難されましたか?いつClassTagを使用する必要がありますか?TypeTagを使用する必要があるのはいつですか
def factoryForAll[T] = new T // will not compile. Runtime doesn't know what T is
Scalaのコンパイラを行うことはできません(現在は非推奨)。 Manifest
には、タイプに関する情報を含むerasure
のようなメソッドがあります。だから私は、ジェネリック型のオブジェクトを作成するには、次のことができないT
def factoryForall[T](implicit ev:Manifest[T]) = ev.erasure.newInstance
scala> factoryForAll[String]
res1:Any=""
scala> class C
defined class C
scala> factoryForAll[C]
res5: Any = [email protected]
質問1 - 興味深い、それがintのために働く(またはフロート)しないのですか?どうして?
scala> factoryForAll[Int]
java.lang.InstantiationException: int
質問2 - なぜ廃止予定マニフェストましたか? Scalaの2.12はまだManifest
クラス(https://www.scala-lang.org/api/current/scala/reflect/Manifest.html)を持っている - 私は新しいバージョン、TypeTag
は、より豊かな情報を持っているが、私はマニフェストにおける欠点
質問3何であったかを理解していないことを理解しています。 Manifest
が悪い場合、Scalaにはまだそれがありますか?ドキュメントではManifest
を使用してArrays
のGeneric型を作成することを指していますが、配列はClassTag
でも実装できます。では、なぜScalaにはまだManifest
があるのですか? TypeTag
に来る
scala> def makeArray[T](len:Int)(implicit ev:ClassTag[T]) = new Array[T](len)
makeArray: [T](len: Int)(implicit ev: scala.reflect.ClassTag[T])Array[T]
scala> makeArray[String](4)
res39: Array[String] = Array(null, null, null, null)
scala> makeArray[Int](4)
res40: Array[Int] = Array(0, 0, 0, 0)
scala> val al = makeArray[List[Int]](2)
al: Array[List[Int]] = Array(null, null)
scala> al(0) = List(1)
scala> al(1) = List(2,3)
、3種類があります。 Scalaのドキュメント(http://docs.scala-lang.org/overviews/reflection/typetags-manifests.html)と中(https://medium.com/@sinisalouc/overcoming-type-erasure-in-scala-8f2422070d20)のチュートリアルを参照すると、私はTypeTag
とClassTag
のユースケースが異なることを理解しています。 ClassTagでは、第1レベルの消去を超えて型を区別することはできません。
//method to extract a type from a collection
def extractType[T](col:Iterable[Any])(implicit ev:ClassTag[T]) = {
val it =col.iterator
while (it.hasNext) {
val el = it.next
el match {
case x:T => println("got T")
case _ => println("not T")
}}}
extractType: [T](col: Iterable[Any])(implicit ev: scala.reflect.ClassTag[T])Unit
scala> extractType[Int](List(1,2,3,"hello"))
got T
got T
got T
not T
scala> extractType[List[Int]](List(List(1),List(2),List(3),List("hello")))
got T
got T
got T
got T //this should be not T
Question4:ClassTag
は消去の第一レベルを区別することができない場合は、私がList[Set[Int]]
でString
を追加しようとすると、なぜ私は次のエラーを取得しますか。 Int
は消去されていませんか?
scala> def makeArray[T](len:Int)(implicit ev:ClassTag[T]) = new Array[T](len)
makeArray: [T](len: Int)(implicit ev: scala.reflect.ClassTag[T])Array[T]
scala> val al = makeArray[List[Set[Int]]](2)
al: Array[List[Set[Int]]] = Array(null, null)
scala> al(0) = List(Set(2))
scala> al(1) = List(Set("2"))
<console>:28: error: type mismatch;
found : String("2")
required: Int
al(0) = List(Set("2"))
^
Question5 - なぜ以前の例extractType[List[Int]](List(List(1),List(2),List(3),List("hello")))
では、ScalaはInt
からString
を区別することができませんでしたが、それはal(0) = List(Set(2))
とal(1) = List(Set("2"))
質問6区別 - どのように私はそのextractType
機能などを変更できますか埋め込みタイプをチェックすることができます。私はTypeTagを使用しなければならないことを知っていますが、コレクション内の要素のタイプをチェックする方法はわかりません。
def extractType[T](col:Iterable[Any])(implicit ev:TypeTag[T]) = {
println("class is "+ev.mirror.runtimeClass) //I suppose in TypeTag, runtime is here
val it =col.iterator
while (it.hasNext) {
val el = it.next
el match {
case x:T => println("got T") //this doesn't compile. What should I check for?
case _ => println("not T")
}}}