6

方法があれば...

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

...必要に応じてContext Boundsを追加できAます。このメソッドが のコンポーネント タイプを調べて、Arrayこれが のサブタイプである場合は true を返しますA。たとえば、次のようになります。

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

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

2.10 より前では、これは次のように行われていました。

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]

これに対する私の最初の推測は次のとおりです。

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
4

2 に答える 2

8

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 テスト:

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

(完全を期すため、OPによるこの編集)

プロパティをscala-reflect.jar保持しない別の解決策 ( を必要としない) は、 aをエクストラクタとして使用することです。Float <:< AnyVal is trueClassTag

scala> def arrayConformsTo[A](as: Array[_])(implicit arrayOfA: ClassTag[Array[A]]) 
     | = as match {
     |     case arrayOfA(_) => true
     |     case _           => false
     |   }
于 2013-05-29T14:13:14.407 に答える