Scala:如何两次继承相同的特征?

时间:2013-06-25 00:42:29

标签: scala inheritance traits

我正在跟随Odersky的“Scala编程”第2版,在第12.5节“Traits as stackable modification”中,他提供了一个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类与上面的BasicIntQueue类似,WaveForm特征类似于上面的IntQueue

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

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

1 个答案:

答案 0 :(得分:3)

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