当使用带反射的路径依赖类型时,即使我有匹配的“底层类型”,我也会遇到类型不匹配错误。什么是这些“非基础类型”,为什么要检查它们而不是“基础类型”?
在下面的代码中,我希望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),但它可能没有关系。
答案 0 :(得分:5)
这与反射没有任何关系。 b1
和b2
的类型为A
(因为这是newInst
的返回类型)。要调用b1.compare(b2)
来编译,b2
必须包含b1.Impl
类型。编译器只知道它是A
的某个子类型,但它不知道哪一个。{1}}。由于您无法传递A
需要某些A
子类型,因此会出错。
在示例中
val b1 = new B(4)
val b2 = new B(5)
b1.compare(b2) // no errors
两个变量的类型都为B
,而B#Impl
为B
,所以所有内容都要进行类型检查。
答案 1 :(得分:5)
我也是这么想的。该 表达“底层类型”有点 误导,虽然它实际上意味着 “父类型”。理想情况下我想 将newInst的返回类型强制转换为 “className”的类,但看起来 喜欢它在Scala中是不可能的。 “
这并不意味着“父类型”。这种类型恰好是父母。基础类型是指单个类型的扩展。数字5的类型是单身;它的基础类型是Int。大多数人不会将Int称为“父类型”。 (尽管如此,它也是。)
关于这个问题,你可以投它。没有什么能阻挡你:scala不会和java不能。
def main(args: Array[String]) {
val b1 = newInst(4, "B")
val b2 = newInst(5, "B")
b1.compare(b2.asInstanceOf[b1.Impl])
}
% scala Test
diff