【问题标题】:Incompatible type error when overriding type bounds覆盖类型边界时出现不兼容的类型错误
【发布时间】:2020-09-05 07:31:59
【问题描述】:

不明白为什么 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
}

感觉是因为依赖路径的类型,但我不明白到底是什么问题以及是否有好的方法来解决它。

【问题讨论】:

  • 你的用例到底是什么,你的元问题是什么?也许还有另一种建模方式。

标签: scala overriding type-alias path-dependent-type


【解决方案1】:

CB的子类型,BA的子类型,所以CA的子类型但C不是A的子类型SelfBSelf。所以你不能覆盖(在BAX有上限Self(即ASelf)与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 的子类型,您可以使用类型投影来指定它

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 内部,您将 can't refer specificallyCfoo()(除非您实例化 C)。但是您可以在任何地方专门引用ASelfBSelfCSelf,类型投影A#SelfB#SelfC#Self

【讨论】:

    【解决方案2】:

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

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-18
      • 1970-01-01
      • 2022-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-26
      相关资源
      最近更新 更多