标签:
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