[解決済み】Scalaの型消去を回避するにはどうしたらいいですか?または、なぜ私のコレクションの型パラメータを取得することができないのですか?
質問
List[Int]をインスタンス化した場合、そのインスタンスがListであることは検証でき、その個々の要素がIntであることも検証できるが、List[Int]であることは簡単に検証できないのがScalaの悲しいところである。
scala> List(1,2,3) match {
| case l : List[String] => println("A list of strings?!")
| case _ => println("Ok")
| }
warning: there were unchecked warnings; re-run with -unchecked for details
A list of strings?!
uncheckedオプションは、タイプ消去に直接責任を負わせるものです。
scala> List(1,2,3) match {
| case l : List[String] => println("A list of strings?!")
| case _ => println("Ok")
| }
<console>:6: warning: non variable type-argument String in type pattern is unchecked since it is eliminated by erasure
case l : List[String] => println("A list of strings?!")
^
A list of strings?!
それはなぜか、どうすれば回避できるのか?
どうすれば解決するの?
<ブロッククオート
この回答では
Manifest
-これは Scala 2.10 で非推奨となった API です。より最新の解決策については、以下の回答を参照してください。
ScalaがType Erasureで定義されたのは、Java Virtual Machine(JVM)がJavaと違ってジェネリックを取得しなかったからです。これは、実行時に、クラスだけが存在し、その型パラメータは存在しないことを意味します。この例では、JVMはそれが
scala.collection.immutable.List
でパラメータ化されていることは知らない。
Int
.
幸いなことに、Scalaにはそれを回避するための機能があります。それは マニフェスト . マニフェストは、型を表すオブジェクトをインスタンスとするクラスです。これらのインスタンスはオブジェクトであるため、それらを渡したり、保存したり、一般的にそれらのメソッドを呼び出すことができます。暗黙のパラメータをサポートすることで、非常に強力なツールになります。例えば、次のような例を見てみましょう。
object Registry {
import scala.reflect.Manifest
private var map= Map.empty[Any,(Manifest[_], Any)]
def register[T](name: Any, item: T)(implicit m: Manifest[T]) {
map = map.updated(name, m -> item)
}
def get[T](key:Any)(implicit m : Manifest[T]): Option[T] = {
map get key flatMap {
case (om, s) => if (om <:< m) Some(s.asInstanceOf[T]) else None
}
}
}
scala> Registry.register("a", List(1,2,3))
scala> Registry.get[List[Int]]("a")
res6: Option[List[Int]] = Some(List(1, 2, 3))
scala> Registry.get[List[String]]("a")
res7: Option[List[String]] = None
要素を格納するとき、その要素の "マニフェスト"も格納します。マニフェストとは、Scalaの型を表すインスタンスを持つクラスです。これらのオブジェクトは、JVMが持っているよりも多くの情報を持っており、それによって、完全な、パラメータ化された型をテストすることができます。
ただし
Manifest
はまだ発展途上の機能です。その限界の一例として、今のところ分散について何も知らないし、すべてが共変数であると仮定している。現在開発中のScalaリフレクションライブラリが完成すれば、より安定で強固なものになると期待している。
関連
-
[解決済み] Scalaの「コンテキストバウンド」とは何ですか?
-
[解決済み] NoClassDefFoundError: org/apache/hadoop/fs/StreamCapabilities (s3データをsparkで読み込む際に発生します。
-
[解決済み] A の値をキーとして Seq[A] を Map[Int, A] に変換する方法は?
-
[解決済み] Scala マップ foreach
-
[解決済み] sbtのlibraryDependenciesで言うところの++=と+=の違いは何ですか?
-
[解決済み] Scalaのapply関数とは何ですか?
-
[解決済み】Scalaのvarとvalの定義の違いは何ですか?
-
[解決済み】タイプセーフのenum型をモデル化する方法は?
-
[解決済み】コマンドラインパラメータを解析する最良の方法?[クローズド]
-
[解決済み] Scalaの==と.equalsの違いは何ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] Scala underscore - ERROR: 展開された関数のパラメータ型が見つかりません。
-
[解決済み] Scalaで「:+」は何を意味するのか
-
[解決済み] scalaのforeachループ
-
[解決済み] self-typesとtrait subclassの違いは何ですか?
-
[解決済み] Scalaのapply関数とは何ですか?
-
[解決済み】タスクがシリアライズされない:オブジェクトではなくクラスに対してのみクロージャの外で関数を呼び出すとjava.io.NotSerializableExceptionが発生する
-
[解決済み】Scalaのウェブフレームワークは何がありますか?[クローズド]
-
[解決済み】ScalaのJavaConvertersとJavaConversionsの違いは何ですか?
-
[解決済み] Scalaの識別子 "implicitly "とは?
-
[解決済み] Scalaの==と.equalsの違いは何ですか?