下面的代码段按预期返回true:
import scala.reflect.runtime.universe._
typeOf[Seq[Int]] <:< typeOf[Traversable[Int]]
但是这个片段没有:
val s = Seq[Int](1,2,3)
val m = runtimeMirror(this.getClass.getClassLoader)
val t = m.reflect(s).symbol.typeSignature
t <:< typeOf[Seq[Int]]
我确信我只是错过了一些明显的东西,但我已经在REPL上工作了几个小时,还没有解决它。如有任何建议,我将不胜感激。
1) typeOf[...]
从Java擦除中保留了确切的Scala类型,然而,obj.getClass
(因此m.reflect(obj)
,在掩护下使用getClass
)没有。因此,在没有额外编译时工作的情况下,通过反射s
可以获得的最佳运行时反射是Seq[_]
(它将无法通过子类型测试)。如果您需要在运行时记住某些东西的确切Scala类型,请使用类型标记(就像typeOf
一样)或宏(就像类型标记一样)。
2) .symbol.typeSignature
不会工作,因为那是ClassInfoType
(即一种类型,它封装了父类类型和类类型成员的列表)。类信息类型非常适合检查成员(可能也适用于基类,也可能适用于其他一些东西,但我不确定),但不适合其他所有东西。您可能希望使用.symbol.asType.toType
之类的参数,它将返回TypeRef
(即在我们的示例中为scala.collection.immutable.::
-注意这里缺少任何类型参数!)。不幸的是,由于#1中描述的擦除,这仍然不能正常工作。
您不需要反射来确定给定的值是否符合给定的静态已知类型。(至少)有两种方法可以做到这一点:
if (someValue.isInstanceOf[SomeType])
...
else
...
或
someValue match {
case st: SomeType => ...
case _ =>
}