无法弄清楚为什么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
的子类型。所以你不能覆盖(在B
)A
的X
具有上限Self
(即A
的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
的子类型,则可以使用类型投影来指定它
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
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
下限可以解决这个问题。