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

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

不知道为什么 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的子类型,所以C A 的子类型,但 C 不是 ASelfBSelf。所以你不能覆盖(在B中)AX有上限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 但这并不意味着 A SelfBSelf 可以。

您可以使用下限修复编译

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 你可以用 type 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 里面你 can't refer specificallyCfoo()(除非你实例化 C)。但是你可以到处特指ASelfBSelfCSelf 类型投影 A#SelfB#SelfC#Self

关于scala - 覆盖类型边界时出现不兼容的类型错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63751517/

相关文章:

scala - 在 Akka Streams 中模拟源

java - 如何检测消息过多? [ Akka Actor ]

julia - 自定义类型别名的 TypeError typeassert

c++ - 如何在 C++ 中转发声明别名模板

javascript - SailsJs - 覆盖 Controller 默认方法

string - Go 中别名类型之间的转换会创建副本吗?

scala - 如何从广播的 Akka 流中获取订阅者和发布者?

scala - 集群 Akka/Scala actor

java - 如何在不覆盖之前数据的情况下使用 hashmap.put? ( java )

Javascript 属性镜像到另一个实例