覆盖类型边界时出现不兼容的类型错误

Incompatible type error when overriding type bounds

无法弄清楚为什么 scalac 在这里不开心 (2.12):

trait A {
  type Self <: A
  type X <: Self
}

trait B extends A {
  override type Self <: B
  override type X = C // error: overriding type X in trait A with bounds <: B.this.Self
}

trait C extends B {
  override type Self = C
}

感觉是路径依赖类型的问题,但我不明白到底哪里出了问题,有没有什么好的方法可以解决。

CB的子类型,BA的子类型,所以CA的子类型但是 C 不是 ASelfBSelf 的子类型。所以你不能用C 不满足边界(即 BSelf)。

trait A {
  type Self <: A
  type X <: Self

  // implicitly[C <:< Self] // doesn't compile
}

trait B extends A {
  override type Self <: B
  // override type X = C 

  // implicitly[C <:< Self] // doesn't compile
}

trait C extends B {
  override type Self = C
}

CSelf等于C但这并不意味着ASelfBSelf 确实如此。

您可以使用下限修复编译

trait A {
  type Self <: A
  type X <: Self
}

trait B extends A {
  override type Self >: C <: B // >: C is added
  override type X = C 
}

trait C extends B {
  override type Self = C
}

或者,如果您的意思是 AX 不是 ASelf 的子类型,而是 CSelf 你可以用类型 projection

指定它
trait A {
  type Self <: A
  type X <: C#Self // here
}

trait B extends A {
  override type Self <: B
  override type X = C
}

trait C extends B {
  override type Self = C
}

我想误会是因为 defs

trait A {
  def foo(): String = "A#foo()"
  def bar(): String = s"bar=A#bar(), foo=${foo()}"
}

trait B extends A {
  def foo(): String = "A#foo()"
}

trait C extends B {
  override def foo(): String = "C#foo()"
}

当我们在 Abar() 中写 foo() 时,我们实际上指的不是 Afoo() 而是实现的 foo().这是可能的,因为方法实现是在运行时后期解析的。但是类型会在编译时提前解析。所以当你写

trait A {
  type Self <: A
  type X <: Self
}
X 上限中的

SelfASelf,而不是实现的 Self.

OOP 原则说在 A 中你 Cfoo()(除非你实例化 C)。但是你可以在任何地方具体引用 ASelfBSelfCSelf 类型投影 A#Self, B#Self, C#Self.

与 Dmytro Mitin 的回答略有不同:如果您对 B 的定义是合法的,则可以进一步扩展

trait D extends B {
  override type Self = D  // satisfies Self <: B
}

但是 X <: Self 不成立(X 仍然是 C,继承自 B)。

更一般地说,B 中的约束应该暗示 A 中的约束,但它们不是;添加 >: C 下限可以解决此问题。