2013-05-29 6 views
5

私はメソッドを持っている場合は...新しいリフレクションAPIを使用して、配列のコンポーネントタイプが型パラメータに準拠しているかどうかを確認するにはどうすればよいですか?必要に応じて、私は<code>A</code>に<em>コンテキスト境界</em>を追加することができます

def arrayConformsTo[A](as: Array[_]) = ??? 

...。このメソッドでArrayのコンポーネントタイプを調べ、Aのサブタイプであればtrueを返します。

def arrayConformsTo[A: Manifest](as: Array[_]) = 
    ClassManifest.fromClass(as.getClass.getComponentType) <:< manifest[A] 

しかし、これは今、この時非推奨の警告

<console>:8: warning: method <:< in trait ClassManifestDeprecatedApis is deprecated: Use scala.reflect.runtime.universe.TypeTag for subtype checking instead 
     ClassManifest.fromClass(as.getClass.getComponentType) <:< manifest[A] 
                 ^
<console>:8: warning: value ClassManifest in object Predef is deprecated: Use scala.reflect.ClassTag instead 
     ClassManifest.fromClass(as.getClass.getComponentType) <:< manifest[A] 

私の最初の推測でコンパイル:だから、たとえば次のよう

arrayConformsTo[Int](Array(1, 2, 3)) //returns true 

arrayConformsTo[String](Array(1, 2, 3)) //returns false 

前2.10に、これが行われていたであろう

scala> def arrayConformsTo[A: reflect.ClassTag](as: Array[_]) = 
    | reflect.ClassTag(as.getClass.getComponentType) <:< implicitly[reflect.ClassTag[A]] 

は、しかし、これは、同様

<console>:8: warning: method <:< in trait ClassManifestDeprecatedApis is deprecated: Use scala.reflect.runtime.universe.TypeTag for subtype checking instead 
     reflect.ClassTag(as.getClass.getComponentType) <:< implicitly[reflect.ClassTag[A]] 
               ^

それはTypeTagを使用するように私に指示非推奨の警告を与えます。しかしどうですか?これは反射を求めるのに有効なものでもありますか?


付録:これはそれがAnyValのために動作しませんが、私は必要なもののために合理的にうまく動作するようです:

scala> def arrayConformsTo[A: reflect.ClassTag](as: Array[_]) = 
    | implicitly[reflect.ClassTag[A]].runtimeClass isAssignableFrom as.getClass.getComponentType 

答えて

7

ScalaのリフレクションAPIは確かにかなり迷路ですが、少なくともそれは包括的である:

import scala.reflect.runtime.{universe => ru} 
def arrayConformsTo[A: ru.TypeTag](as: Array[_]) = { 
    val mirror = ru.runtimeMirror(getClass.getClassLoader) 
    val classSym = mirror.classSymbol(as.getClass.getComponentType) 
    classSym.toType <:< implicitly[ru.TypeTag[A]].tpe 
} 

REPLテスト:理由のためにOPによって

scala> arrayConformsTo[Float](Array[Float]()) 
res9: Boolean = true 

scala> arrayConformsTo[Int](Array[Float]()) 
res10: Boolean = false 

scala> arrayConformsTo[AnyVal](Array[Float]()) 
res11: Boolean = true 

scala> arrayConformsTo[AnyVal](Array[Float]()) 
res12: Boolean = true 

scala> arrayConformsTo[Any](Array[Float]()) 
res13: Boolean = true 

scala> arrayConformsTo[Any](Array[Float]()) 
res14: Boolean = true 

scala> arrayConformsTo[AnyRef](Array[Float]()) 
res15: Boolean = false 

scala> arrayConformsTo[AnyRef](Array[Float]()) 
res16: Boolean = false 

(この編集完全性の

もう1つの解決策(scala-reflect.jar)、Float <:< AnyVal is trueプロパティを保持しないものを抽出としてClassTagを使用することであるとはいえ:

scala> def arrayConformsTo[A](as: Array[_])(implicit arrayOfA: ClassTag[Array[A]]) 
    | = as match { 
    |  case arrayOfA(_) => true 
    |  case _   => false 
    | } 
+0

それは素晴らしいです!あなたがいなくても、私はあなたの答えを編集してそれを受け入れる前に別の解決策を与えるつもりです –

1

これは、任意のコンパイラの警告O/W私の作品:

def arrayConformsTo[A](as: Array[_])(implicit t:ClassTag[A]) = { 
    ClassTag(as.getClass().getComponentType()) equals t 
} 

これはtrueを印刷してからfalse

println(arrayConformsTo[Int](Array(1,2,3))) 
println(arrayConformsTo[String](Array(1,2,3))) 
+1

しかし、これはちょうど彼の中oxbow_lakesから最新の実装と同様に、 'AnyVal'も' Any'のために動作しません。付録。 –

+1

良い点。私はあなたの答えが好きです。 – cmbaxter

関連する問題