问题描述
在这里无法弄清为什么斯卡乐不满意(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
的子类型,但是{ {1}}不是C
的{{1}}或A
的{{1}}的子类型。因此,您不能使用Self
的{{1}}的{{1}}具有上限B
(即Self
的{{1}})来覆盖B
不满足界限(即A
的{{1}})。
X
Self
的{{1}}等于A
,但这并不意味着Self
的{{1}}或C
的{{ 1}}。
您可以使用下限修复编译
B
或者如果您是说Self
的{{1}}是不是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
}
的{{1}}而是C
的{{1}}的子类型您可以使用投影类型指定它
Self
我猜误解是因为C
s
A
当我们在Self
的{{1}}中写入B
时,实际上并不是指Self
的{{1}},而是指实现的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
的{{1}},而不是实现的C
。
OOP原则说,在Self
中,您can't refer specifically到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
}
的{{1}}(除非您实例化def
)。但是您到处都可以使用类型为{{的类型}来具体引用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()"
}
的{{1}},foo()
的{{1}},A
的{{1}} 1}},bar()
,A
。
与米米·米汀(Dmytro Mitin)的回答稍有不同:如果您对B
的定义是合法的,则可以进一步扩展
trait D extends B {
override type Self = D // satisfies Self <: B
}
但是X <: Self
不会成立(X
仍然是C
,继承自B
)。
更笼统地说,B
中的约束应该暗示A
中的约束,而实际上不是。添加>: C
下限可以解决此问题。