我想做的是:
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)
会有所帮助。
答案 0 :(得分:2)
我会避免重写和依赖某些超级/子类型调用。为什么不实现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 = ???
}
答案 1 :(得分:1)
你问:如果在混合之后super.f
是抽象的(或“不完整的”),请选择一个具体的f来服务。也许你说的是,只有恰好有一个这样的f,并且它是在当前模板中定义的。
一个问题是,如果在初始化期间调用抽象f,并调用子类中的具体f,则子类的初始化器尚未运行。
这是模板方法的常见问题。我认为Josh Bloch的书说不要这样做。
但是编写可堆叠特征的人无法知道超级是以这种方式转变的。