我想做的是:
trait Addable[T]{
def plus(x: T): T
}
trait AddableWithBounds[T] extends Addable[T] {
abstract override def plus(x: T): T = limitToBounds(super.plus(x))
def limitToBounds(x: T): T = ... //Some bounds checking
}
class Impl(num: Int) extends AddableWithBounds[Impl] {
override def plus(x: Impl) = new Impl(num + x.num)
}
通过阅读各种帖子,这似乎是不可能的,因为在类线性化之后,堆叠特性只在其右侧的类中寻找super.plus(x:T)的实现
不过,这是一个技术性的争论,我对这个问题很感兴趣:实现不能从基类中获取有根本原因吗?因为正如你在这个例子中看到的,在知道需要添加的实际数据类型之前,不可能实现plus方法,但在特性中实现边界检查似乎是合理的。
作为一个想法:如果问题是在这种情况下,不清楚基类中覆盖了哪个加号,可能是像这样的范围标识符
def Addable[Impl].plus(x: Impl) = new Impl(num + x.num)
会有所帮助。
我会避免重写和依赖某些超级/子类型调用。为什么不实现plus
并要求子类型提供一个辅助抽象方法:
trait Addable[T] {
def plus(x: T): T
}
trait AddableWithBounds[T] extends Addable[T] {
final def plus(x: T): T = limitToBounds(plusImpl(x))
protected def plusImpl(x: T): T
def limitToBounds(x: T): T = ??? //Some bounds checking
}
class Impl(num: Int) extends AnyRef with AddableWithBounds[Impl] {
protected def plusImpl(x: Impl): Impl = ???
}
您在问:如果super.f
在混合后是抽象的(或"不完整的"),请选择一个具体的f来提供。也许你是在说,只有在当前模板中定义了一个这样的f的情况下。
一个问题是,如果在初始化期间调用抽象f,并调用子类中的具体f,则子类的初始化器尚未运行。
这是模板方法的常见问题。我觉得Josh Bloch的书上说不要那样做。
但写可堆叠特征的人无法知道超级人物是以这种方式转变的。