Scala 反射:上下文绑定的类型标记与类型参数不匹配



让我们从一个示例代码开始:

import scala.reflect.runtime.universe._
class A[T] {
}
def foo[T: TypeTag](a: A[T]) {
  println(typeTag[T])
}
val a = new A[Int]
val b: A[_] = a
foo(a)
foo(b)

输出为:

TypeTag[Int]
TypeTag[_$1]

嗯,我不知道TypeTag[_$1]是什么,但它看起来确实很漂亮。尽管如此,我还是认为foo对世界的期望在这里被违反了,因为如果foo被A[Int]的实例调用,那么它就保证具有Int类型标签,而不是其他一些模糊的类型标签。此外,与weektypetags相比,typetags不应该是"具体的"吗?

现在我当然看到编译器不能在第二个foo调用中告诉a的类型参数,所以我的期望不是我神奇地得到typeTag[Int]作为第二个调用的输出,而是我希望有一个编译时错误。

我的误解在哪里?

一些无用的猜测有人可能会说,正在发生的事情是用参数类型A[_]调用foo,或者更明确地说,是存在类型A[S] forSome { type S }。然后typeTag以某种方式捕获"_"。但这实际上没有意义,因为foo对某些具体的T期望A[T],而上述存在类型对任何具体的T都不是A[T]。或者是带参数A[Any]的调用?但为什么不是TypeTag[Any],更严重的是,A不是协变的,所以这也是明显错误的。

Type标记是在编译时创建的,值在编译时不可用。一旦将A[Int]强制转换为存在类型A[_],有关该类型参数的所有信息都将丢失。

如果它们是在运行时根据值创建的,则类型擦除将使不可能知道A的参数。即使在编译时已知是A[Int]的东西,在运行时也最多是A[Object](除非AArray,但我们不去那里)。

所以你的猜测是正确的,对于foo(b),类型参数确实是来自存在的A[_]_,并且匿名类型变量打印为_$1

相关内容

  • 没有找到相关文章

最新更新