如果我有方法......
def arrayConformsTo[A](as: Array[_]) = ???
...我可以根据需要将上下文界限添加到A
。我希望此方法查看Array
的组件类型,如果这是A
的子类型,则返回true。所以,例如:
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
答案 0 :(得分: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测试:
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
),虽然不保留Float <:< AnyVal is true
属性,但是使用ClassTag
作为提取器:
scala> def arrayConformsTo[A](as: Array[_])(implicit arrayOfA: ClassTag[Array[A]])
| = as match {
| case arrayOfA(_) => true
| case _ => false
| }
答案 1 :(得分:1)
这适用于我没有任何编译器警告:
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)))