为什么不可能(在scala中)在实现基类中提供抽象重写方法的实现



我想做的是:

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的书上说不要那样做。

但写可堆叠特征的人无法知道超级人物是以这种方式转变的。

最新更新