2

我正在关注 Odersky 的“Scala 编程”第 2 版和第 12.5 节“作为可堆叠修改的特征”,他提出了IntQueue一个特征,该特征将您插入到队列中的任何值加倍:

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)
 }
}

然后,这本书展示了您可以实例化一个队列,该队列将您通过 插入其中的每个整数加倍new BasicIntQueue with Doubling。我想做的是创建一个类似的队列,将每个整数乘以 4,如下所示new BasicIntQueue with Doubling with Doubling:但是,这会触发编译错误“ trait Doubling is inherited twice”。调查一下,我想这与线性化的局限性有关。特别是给定的特征不能在类层次结构的线性化中出现两次。

那么,达到我想要的效果的最佳方法是什么?

以下是有关我的“真实世界”用例的更多信息,以防答案取决于此:

我有一个类SoundFile,它读取一个 .wav 文件,并产生一个SoundFile对象,它扩展了一个WaveForm特征。类SoundFile同上BasicIntQueueWaveForm特质IntQueue同上。

我有 2 个类似于 的特征Doubling,一个叫做Echo,一个叫做Reverse

我想写new SoundFile("myFile.wav") with Reverse with Echo with Reverse,但我遇到了关于从Reversetrait 继承两次的相同编译错误。

4

1 回答 1

4

不幸的是,你不能从同一个特征继承两次。相反,您应该使用其他一些机制。例如,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 回答