如何使用Scala 2.10反射API检查运行时实例是否符合某种类型?

时间:2013-04-14 19:53:12

标签: scala reflection

以下代码段按预期返回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上工作了几个小时并且还没有完成它。任何建议将不胜感激。提前谢谢。

2 个答案:

答案 0 :(得分:6)

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中描述的擦除,它仍然无法开箱即用。

答案 1 :(得分:2)

您不需要反射来确定给定值是否符合给定的静态已知类型。有两种方法(至少)这样做:

if (someValue.isInstanceOf[SomeType])
  ...
else
  ...

someValue match {
  case st: SomeType => ...
  case _ =>
}