当使用带有反射的路径相关类型时,即使我有匹配的“底层类型”,我也会收到类型不匹配错误。这些“非底层类型”是什么?为什么检查它们而不是“底层类型”?
在下面的代码中,我希望 compare
方法仅接受 A 的相同类型子类作为参数。错误出现在最后一行。
abstract class A(val a:Int) {
type Impl <: A
def compare(other:Impl) {
if(a==other.a) println("equal") else println("diff")
}
}
class B(a:Int) extends A(a) {type Impl = B}
object Test {
def newInst(a: Int, className: String) = {
val constr = Class.forName(className).getConstructors()(0)
constr.newInstance(a.asInstanceOf[AnyRef]).asInstanceOf[A]
}
def main(args: Array[String]) {
val b1 = newInst(4, "B")
val b2 = newInst(5, "B")
b1.compare(b2) // type mismatch error here
}
}
在最后一行我收到此错误:
error: type mismatch;
found : b2.type (with underlying type A)
required: b1.Impl
由于 b2 的类型与 b1 的类型(即 A)相同,因此我预计这不会生成错误。由于某种原因,这些路径相关类型与使用反射时的“底层类型”不同。为什么?
如果我不使用反射,它会起作用:
val b1 = new B(4)
val b2 = new B(5)
b1.compare(b2) // no errors
(在我的例子中我确实需要使用反射)。 newInst()
可以使用反射将对象作为类“B”返回吗?这有帮助吗?使用抽象类型时是否存在类型删除?
这是我发现的关于相同错误的唯一引用 ( on this forum ),但可能不相关。
最佳答案
这与反射没有任何关系。 b1
和 b2
的类型是 A
(因为这是 newInst
的返回类型)。要编译调用 b1.compare(b2)
,b2
必须具有类型 b1.Impl
。编译器只知道它是 A
的某种子类型,但不知道是哪一个。由于您无法传递需要 A
某些子类型的 A
,因此您会收到错误。
在示例中
val b1 = new B(4)
val b2 = new B(5)
b1.compare(b2) // no errors
两个变量的类型均为 B
,并且 B#Impl
是 B
,因此所有内容都会进行类型检查。
关于reflection - 路径相关类型与 "underlying types",检查哪些类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4880529/