[英]Override abstract type member in stackable trait pattern
假設我們想要定義如何在某些數據上累積結果的方法:
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)
}
由於超類和混合類具有相同的方法名稱(顯然),我們不能引用正確的方法。 我唯一的選擇是使用作文嗎?
我怎樣才能堆疊這樣的操作?
第一種方法有一個基本的理論問題:
假設我們被允許寫這些特征。 然后考慮以下事項:
val acc = new XAccumulator with TraceYAccumulator
val xacc = acc: XAccumulator
由於xacc
是XAccumulator
,我們知道xR =:= Int
。 糟糕!
第二種方法存在實現問題:您無法從同一特征的不同實例繼承。
illegal inheritance; anonymous class $anon inherits different type instances of trait Accumulator: Accumulator[Int] and Accumulator[(Seq[Int], Int)]
因此,組合(或者某些類型類hackery)似乎是唯一的選擇。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.