覆盖类型边界时出现不兼容的类型错误
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
}
感觉是路径依赖类型的问题,但我不明白到底哪里出了问题,有没有什么好的方法可以解决。
C
是B
的子类型,B
是A
的子类型,所以C
是A
的子类型但是 C
不是 A
的 Self
或 B
的 Self
的子类型。所以你不能用C
不满足边界(即 B
的 Self
)。
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
}
C
的Self
等于C
但这并不意味着A
的Self
或B
的Self
确实如此。
您可以使用下限修复编译
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
}
或者,如果您的意思是 A
的 X
不是 A
的 Self
的子类型,而是 C
的 Self
你可以用类型 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
}
我想误会是因为 def
s
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()"
}
当我们在 A
的 bar()
中写 foo()
时,我们实际上指的不是 A
的 foo()
而是实现的 foo()
.这是可能的,因为方法实现是在运行时后期解析的。但是类型会在编译时提前解析。所以当你写
trait A {
type Self <: A
type X <: Self
}
X
上限中的 Self
是 A
的 Self
,而不是实现的 Self
.
OOP 原则说在 A
中你 到 C
的 foo()
(除非你实例化 C
)。但是你可以在任何地方具体引用 A
的 Self
、B
的 Self
、C
的 Self
类型投影 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
下限可以解决此问题。
无法弄清楚为什么 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
}
感觉是路径依赖类型的问题,但我不明白到底哪里出了问题,有没有什么好的方法可以解决。
C
是B
的子类型,B
是A
的子类型,所以C
是A
的子类型但是 C
不是 A
的 Self
或 B
的 Self
的子类型。所以你不能用C
不满足边界(即 B
的 Self
)。
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
}
C
的Self
等于C
但这并不意味着A
的Self
或B
的Self
确实如此。
您可以使用下限修复编译
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
}
或者,如果您的意思是 A
的 X
不是 A
的 Self
的子类型,而是 C
的 Self
你可以用类型 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
}
我想误会是因为 def
s
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()"
}
当我们在 A
的 bar()
中写 foo()
时,我们实际上指的不是 A
的 foo()
而是实现的 foo()
.这是可能的,因为方法实现是在运行时后期解析的。但是类型会在编译时提前解析。所以当你写
trait A {
type Self <: A
type X <: Self
}
X
上限中的 Self
是 A
的 Self
,而不是实现的 Self
.
OOP 原则说在 A
中你 C
的 foo()
(除非你实例化 C
)。但是你可以在任何地方具体引用 A
的 Self
、B
的 Self
、C
的 Self
类型投影 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
下限可以解决此问题。