2

私は Odersky の「Programming in Scala」第 2 版をフォローしており、セクション 12.5「スタック可能な変更としてのトレイト」で、彼はIntQueueキューに挿入する値を 2 倍にするトレイトを提示しています。

import scala.collection.mutable.ArrayBuffer
abstract class IntQueue {
 def get(): Int
 def put(x: Int)
}

class BasicIntQueue extends IntQueue {
 private val buf = new ArrayBuffer[Int]
 def get() = buf.remove(0)
 def put(x: Int) { buf += x }
}

trait Doubling extends IntQueue {
 abstract override def put(x: Int) {
  super.put(2 * x)
 }
}

この本は、 を介して挿入するすべての整数を 2 倍にするキューをインスタンス化できることを示していますnew BasicIntQueue with Doubling。私がやりたかったのは、次のように、すべての整数を 4 倍にする同様のキューを作成することでしたnew BasicIntQueue with Doubling with Doubling。ただし、これによりコンパイル エラー " trait Doubling is inherited twice" が発生します。これを調べてみると、これは線形化の制限と関係があると思います。具体的には、特定の特性がクラス階層の線形化で 2 回出現することはありません。

では、私が望む効果を達成するための最良の方法は何ですか?

答えがこれに依存する場合に備えて、私の「現実世界」のユースケースに関する詳細情報を次に示します。

SoundFile.wav ファイルを読み取り、特性SoundFileを拡張するオブジェクトを生成する classがあります。クラスは上記に類似してWaveFormおり、トレイトは上記に類似しています。SoundFileBasicIntQueueWaveFormIntQueue

私は に似た 2 つの特性を持っていますDoubling。1 つは と呼ばれ、もう 1 つはEchoと呼ばれReverseます。

を書きたかったのですが、トレイトnew SoundFile("myFile.wav") with Reverse with Echo with Reverseから 2 回継承するという同じコンパイル エラーに遭遇しました。Reverse

4

1 に答える 1

4

残念ながら、同じ特性を 2 回継承することはできません。代わりに、他のメカニズムを使用する必要があります。たとえば、ReverseEchoはどちらも波形の操作です。あなたが持っている可能性があります

val reverse = (w: Waveform) => // produce a reverse waveform
val echo =    (w: Waveform) => // copy the waveform onto itself with delay
new SoundFile("myFile.wav", reverse andThen echo andThen reverse)

または何か。

単なる関数以上の変更が必要な場合は、独自のクラスで機能への変更をカプセル化する必要があります。

trait Transform { self =>
  def apply(w: Waveform): Waveform
  def time: Double
  def andThen(t: Transform) = new Transform {
    def apply(w: Waveform) = t(self(w))
    def time = self.time + t.time
  }
}
val reverse = new Transform { def time = 0.0; def apply ... }
val echo    = new Transform { def time = 1.0; def apply ... }
// Same deal after here
于 2013-06-25T01:04:16.437 に答える