为什么无法覆盖已经实现的抽象类型?

8

给定以下代码:

class A {

  class B

  type C <: B

  trait D

}

class E extends A {

  type C = B

}

class F extends E {

  override type C = B with D

}

为什么Scala IDE中的Eclipse Indigo IDE的展示编译器会出现错误信息“overriding type C in class E,which equals F.this.B; type C has incompatible type”?
毕竟,类“B”只是通过特质“D”进行了“修饰”,因此两个类型定义具有相同的基本类型,即“B”。因此,它们是兼容的类型定义。
下面的代码可以正常工作。我认为类型赋值的规则与变量赋值类似,例如:
class Foo

trait Bar

val a: Foo =  new Foo

val fooWithBar: Foo = new Foo with Bar

我理解错了吗?


1
Foo与Bar是Foo的子类型。问题不在于此。即使重新定义为子类型,您也不允许在其固定时重新定义类型成员。如果有class Bar extends Foo,则也不能将类型成员从Foo重新定义为Bar。 - Didier Dupont
1个回答

14

它们不兼容,类型C可能在逆变位置使用

class E extends A {
  type C = B
  def f(c: C)
}


class F extends E {
  override type C = B with D 
  def f(c: ???)
}

补充说明 假设有一个 e: E 对象,你可以调用 e.f(new B) 方法。那么如果 eval e = new F 呢?


只要被覆盖的类型“C”受到进一步限制并保持其基本类型“B”,为什么这种组合应该是不合理的呢?如果方法“f”接受“B”,那么为什么它不能接受其子类,如重新定义的“B with D”呢? - Tim Friske
3
如果这个方法接受B,那么它肯定也要接受子类型。问题在于F的实例需要带有D的B,因此不再接受简单的B。E的子类型必须在f中接受B。当然,它也会接受子类型。它不能要求参数是一个子类型。 - Didier Dupont
我不确定这是否是正确的反例。原因如下:(抱歉,请忽略,我试图在手机上点击取消,但它却被发布了..) - Iulian Dragos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接