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)
}
}
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:
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.
I have 2 traits that are analogous to Doubling
, one called Echo
and one called 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.
Doubling
, it'd replytrue
, because it IS true; no need to make the fact that it inherits twice apparent in the type system. - Nebu Pookins