abstract class IntQueue {
def get(): Int
def put(x: Int)
}
class BasicIntQueue extends IntQueue {
import scala.collection.mutable.ArrayBuffer
private val buf = new ArrayBuffer[Int]
def get() = buf.remove(0)
def put(x: Int) { buf += x }
}
//trait Doubling extends from IntQueue, this
//means, it can only be mixed with a class
//that also descends from IntQueue
trait Doubler extends IntQueue {
//calls like this are not allowed in normal classes
//here super call will resolve dynamically to the
//trait/class that is in left to this one while mixing
//and gives a concrete implementation to put
abstract override def put(x: Int) { super.put(2 * x) }
}
trait Increment extends IntQueue {
abstract override def put(x: Int) { super.put(x+1) }
}
class MyQ extends BasicIntQueue with Doubler
scala> val q = new MyQ
q: MyQ = MyQ@15bf0c5
//put in Doubler is executed(because its the rightmost component),
//super.put resolves in it
//resolves to put in BasicIntQueue as that is the next concret
//put available to it's left.
scala> q.put(10)
scala> q.put(20)
scala> q.get()
res60: Int = 20 //10 was doubled
scala> q.get()
res61: Int = 40 //20 was doubled
Notice MyQ does nothing else but the mixing only, it has no body. For this we can use the following shorthand code.
val q = new BasicIntQueue with Doubling
Let us check out one more case..
scala> val q = new BasicIntQueue with Incrementer with Doubler
q: BasicIntQueue with Incrementer with Doubler = $anon$1@4cfc65
//rightmost put is applied, which is the put in Doubler, super.put
//in Doubler resolves to put in Incrementer and same in Incrementer
//resolves to put in BasicIntQueue
scala> q.put(10)
scala> q.put(20)
scala> q.get()
res64: Int = 21 //21 = 10*2 + 1
scala> q.get()
res65: Int = 41 //41 = 20*2 + 1
No comments:
Post a Comment