问题描述
我遵循的是Odersky的在Scala中编程"第二版,以及第12.5节作为可堆叠修改的特性",他介绍了IntQueue
以及一个特征,该特征使您插入队列中的任何值加倍: /p>
I'm following along in Odersky's "Programming in Scala" 2nd edition, and in section 12.5 "Traits as stackable modifications", he presents an IntQueue
along with a trait that doubles any values you insert into the queue:
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
".考虑到这一点,我认为这与线性化的局限性有关.特别是给定的特征不能在类层次结构的线性化中出现两次.
The book then shows that you can instantiate a queue which doubles every integer you insert into it via new BasicIntQueue with Doubling
. What I wanted to do was created a similar queue which multiplies every integer by 4, like this: new BasicIntQueue with Doubling with Doubling
. However, this triggers a compile error "trait Doubling is inherited twice
". Looking into this, I guess this has something to do with the limitations of linearlization; specifically that a given trait cannot appear twice in the linearlization of a class hierarchy.
那么,达到我想要的效果的最佳方法是什么?
What's the best way, then, to achieve the effect I want?
如果答案取决于此,这里有更多关于现实世界"用例的信息:
Here's a bit more information on my "real world" use case, in case the answer depends on this:
我有一个类SoundFile
,该类读取.wav文件,并产生一个SoundFile
对象,该对象扩展了WaveForm
特性. SoundFile
类类似于上面的BasicIntQueue
,并且WaveForm
特性类似于上面的IntQueue
.
I have a class SoundFile
, which reads a .wav file, and yields a SoundFile
object, which extends a WaveForm
trait. The SoundFile
class is analogous to the BasicIntQueue
above, and the WaveForm
trait is analogous to the IntQueue
above.
我有2个与Doubling
类似的特质,一个称为Echo
,另一个称为Reverse
.
I have 2 traits that are analogous to Doubling
, one called Echo
and one called Reverse
.
我想写new SoundFile("myFile.wav") with Reverse with Echo with Reverse
,但是遇到两次关于从Reverse
特征继承的相同编译错误.
I wanted to write new SoundFile("myFile.wav") with Reverse with Echo with Reverse
, but I ran into that same compile error about inheriting from the Reverse
trait twice.
推荐答案
不幸的是,您不能两次继承相同的特征.相反,您应该使用其他机制.例如,Reverse
和Echo
都是波形的操纵.你可能有
Unfortunately you can't inherit from the same trait twice. Instead you should use some other mechanism. For instance, Reverse
and Echo
are both manipulations of the waveform. You could have
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)
或类似的东西.
如果您需要的不仅仅是简单功能的更改,则必须将对功能的修改封装在自己的类中:
If you require more changes than just a simple function, you'll have to encapsulate the modifications to functionality in your own class:
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
这篇关于Scala:如何两次继承相同的特征?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!