Scala 堆叠Traits实现对方法或函数的增强
简单的来说,堆叠Trait类似于AOP,实现对方法功能的增强,而不去修改原有方法的逻辑。
比如我们实现一个队列,我们可以定义一个队列的抽象类,实现入队和出队操作,用scala这样写,和java差不多,
abstract class IntQueue {
def get(): Int
def put(x: Int)
}
我们去实现这个抽象类,
class BasicIntQueue extends IntQueue {
private val buf = new ArrayBuffer[Int]
override def get() = buf.remove(0)
override def put(x: Int) {
buf += x
}
}
测试一下,
object Main87 {
def main(args: Array[String]) {
val queue = new BasicIntQueue
queue.put(10)
queue.put(20)
println(queue.get())
println(queue.get())
}
}
这样是可以实现我们的功能的。但是我们想在put方法上实现更多的功能,比如说给入队的值加倍。
你可能会说直接去修改put方法的逻辑,这样也是可行的,但没有扩展性。比较好的方法还可以是继承父类在实现一个具体的类,put方法的逻辑是加倍。
class BasicIntQueue2 extends IntQueue {
private val buf = new ArrayBuffer[Int]
override def get() = buf.remove(0)
override def put(x: Int) {
buf += 2 * x
}
}
如果现在逻辑又改了,我们要过滤入队的值,比如说值小于等于0 ,那么丢弃,不入队,然后把过滤后的值加倍。这样的话是不是还要实现一个具体的类,实现这样的逻辑?当然可以这么做。然而在java中,运用AOP的思想可以给put方法写一个切面,作用于加倍的put方法。加逻辑,就要写切面,这样也不是很好。在scala中实现这样的功能就是堆叠trait。
我们定义加倍的Trait,
trait Doubling extends IntQueue {
abstract override def put(x: Int) {
println("doubling")
super.put(2 * x)
}
}
定义过滤的Trait,
trait Filtering extends IntQueue {
abstract override def put(x: Int) {
println("filtering")
if (x >= 0) super.put(x)
}
}
这两个trait相当于一个一个的切面,如何把这些逻辑加到基础的put方法上呢?我们可以这样来做
class MyQueue00 extends BasicIntQueue with Doubling with Filtering
object Main87 {
def main(args: Array[String]) {
val q = new MyQueue00
q.put(-1)
q.put(0)
q.put(1)
println(q.get())
println(q.get())
}
}
运行结果,
filtering
filtering
doubling
filtering
doubling
0
2
这个问题就这么优雅的解决了,这样做的好处就是可以很好的复用代码。
一个完成的demo
package com.usoft4
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]
override def get() = buf.remove(0)
override def put(x: Int) {
buf += x
}
}
class BasicIntQueue2 extends IntQueue {
private val buf = new ArrayBuffer[Int]
override def get() = buf.remove(0)
override def put(x: Int) {
buf += 2 * x
}
}
trait Doubling extends IntQueue {
abstract override def put(x: Int) {
println("doubling")
super.put(2 * x)
}
}
trait Incrementing extends IntQueue {
abstract override def put(x: Int) {
println("incrementing")
super.put(x + 1)
}
}
trait Filtering extends IntQueue {
abstract override def put(x: Int) {
println("filtering")
if (x >= 0) super.put(x)
}
}
class MyQueue0 extends BasicIntQueue with Doubling
class MyQueue00 extends BasicIntQueue with Doubling with Filtering
object Main87 {
def main(args: Array[String]) {
val queue = new BasicIntQueue
queue.put(10)
queue.put(20)
println(queue.get())
println(queue.get())
val q = new MyQueue00
q.put(-1)
q.put(0)
q.put(1)
println(q.get())
println(q.get())
val myQueue = new MyQueue0
myQueue.put(10)
println(myQueue.get())
val myQueue2 = (new BasicIntQueue with Filtering with Incrementing)
myQueue2.put(-1)
println("put end")
myQueue2.put(0)
println("put end")
myQueue2.put(1)
println("put end")
println(myQueue2.get())
}
}
=====================END=====================
原文:http://my.oschina.net/xinxingegeya/blog/491539