2017-01-14 28 views
0

"Any"型の値を受け入れ、ジェネリック型引数に "T"を受け入れ、Option [T]を返すジェネリック関数を書くことはできますか?渡された値の実行時の型をチェックしていますか?scala "Any"型を指定されたジェネリック型引数に変換する

私は警告を取得(Scalaのバージョン2.11.7(は、Java HotSpot(TM)64ビットサーバーVMはJava 1.8.0_66))REPLで

def cast[T](x: Any): Option[T] = x match { 
case v: T => Some(v) 
case _ => Option.empty[T] 
} 

を試してみました:

warning: abstract type pattern T is unchecked since it is eliminated by erasure 
      case v: T => Some(v) 

どのようにクラスの型を渡し、ジェネリックではなく明示的な型チェックを行うのですか?

P.S.明らかに型消去のために、上記のコードが爆発します。サンプルREPLとの対話:

scala> val x :Any = 123                      
x: Any = 123                        

scala> cast[Int](x)                       
res0: Option[Int] = Some(123)                    

scala> cast[String](x)                      
res1: Option[String] = Some(123)                   

scala> val x :Any = "dfg"                     
x: Any = dfg                        

scala> cast[Int](x)                       
res2: Option[Int] = Some(dfg)                    

scala> cast[Int](x).get                      
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer       
    at scala.runtime.BoxesRunTime.unboxToInt(BoxesRunTime.java:101)           
    ... 33 elided 

答えて

3

あなたはランタイム型のためClassTagを必要とする:

def cast[T: ClassTag](x: Any): Option[T] = x match { 
    case v: T => Some(v) 
    case _ => Option.empty[T] 
} 

println(cast[Int](1)) 
println(cast[Int]("hello")) 

収量:

Some(1) 
None 
+1

迅速な回答に感謝を。 さらに読む: http://docs.scala-lang.org/overviews/reflection/typetags-manifests.html – sas1138

+0

これには制限がありますので注意してください: 'val list = List(" a "、" b ");キャスト[リスト[Int]](リスト) ' –

+0

@MichaelZajac確かに。すぐに答えを広げてより一般的なものにしよう。 –

関連する問題