簡體   English   中英

以可堆疊特征模式覆蓋抽象類型成員

[英]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

由於xaccXAccumulator ,我們知道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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM