假设我们要定义如何在某些数据上累积结果的方法:
case class Data(x: Int, y: Int)
为此,我们定义了一个特征:
trait Accumulator {
type R
def add(acc: R, d: Data): R
def zero: R
}
还有一个简单的实现:
trait XAccumulator extends Accumulator {
type R = Int
def add(acc: Int, d: Data) = acc + d.x
def zero = 0
}
我想使用 stackable-trait 模式来使用多个这些简单的累加器:
trait TraceYAccumulator extends Accumulator {
abstract override type R = (Seq[Int], super.R)
// fails:
// `abstract override' modifier not allowed for type members
def add(acc: R, d: Data) = {
val r = super.add(acc._2, d)
(acc._1 :+ d.y, r)
}
def zero = (Seq.empty[Int], super.zero)
}
显然我不允许重写抽象类型成员。如何使用可堆叠特征模式更改覆盖方法的结果类型?
我的第二种方法是使用类型参数:
trait Accumulator[R] {
def add(acc: R, d: Data): R
def zero: R
}
trait XAccumulator extends Accumulator[Int] {
def add(acc: Int, d: Data) = acc + d.x
def zero = 0
}
但现在它变得非常奇怪:
trait TraceYAccumulator[T] extends Accumulator[(Seq[Int], T)] {
this: Accumulator[T] =>
def add(acc: (Seq[Int], T), d: Data): (Seq[Int], T) = {
val r = this.add(acc._2, d)
// fails: overloaded method value add with alternatives:
// (acc: (Seq[Int], T),d: Data)(Seq[Int], T) <and>
// (acc: _14695,d: Data)_14695 cannot be applied to (T, Data)
(acc._1 :+ d.y, r)
}
def zero: (Seq[Int], T) = (Seq.empty[Int], this.zero)
}
由于超类和混入类具有相同的方法名称(显然),我们无法引用正确的方法。我唯一的选择是使用组合吗?
我怎样才能堆叠这样的操作?