对比scala,用javascript实现 特质(trait) 的部分特性

超2真神

特质(trait)是scala的一个重要的特性,主要的使用方式有两个方面:1.拓宽瘦接口为胖接口。2.定义可堆叠的改变。
trait相对于多重继承而言最灵活的一方面就是super所指定的对象只有到被混入之后才能确定。
因为特质里面既可以有字段方法,还可以既只写方法的类型,也可以写上方法的实现(不像JAVA的接口那样),而且可以混入到类中,类也可以使用任意多的特质。相当的灵活。

就混入到类中,和胖瘦接口而言,对javascript来说简直就是天生的,不值一提(但javascript的问题是,以弱类型换来的灵活,有时候总感觉灵活的都不像话,特别不容易理解其他jser的代码)。

就[可堆叠的改变]而言:如下scala代码:

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 }
}

// val queue = new BasicIntQueue
// queue.put(10)
// queue.put(20)
// queue.get()
// queue.get()

trait Doubling extends IntQueue {
    abstract override def put(x: Int) { super.put(2 * x) }
}

class MyQueue extends BasicIntQueue with Doubling
// val queue = new MyQueue
// queue.put(10)
// println(queue.get())
val queue = new BasicIntQueue with Doubling
// queue.put(10)
// println(queue.get())

trait Incrementing extends IntQueue {
    abstract override def put(x: Int) { super.put(x + 1) }
}

trait Filtering extends IntQueue {
    abstract override def put(x: Int) {
        if(x >= 0) super.put(x)
    }
}

val queue1 = new BasicIntQueue with Doubling with Incrementing with Filtering
queue1.put(-1)//先执行Filtering,-1 被过滤掉了
queue1.put(0) // 执行过滤,然后 +1,然后 *2
queue1.put(1)
println(queue1.get())
println(queue1.get())

javascript的实现:
代码链接:https://github.com/peichao01/test2/tree/master/javascript/trait

function trait (konstructor, traits) {
    traits = [].slice.call(arguments, 1);
    function _trait(reciever, trait_, parentName){
        for(var methodName in trait_){
            if(reciever.hasOwnProperty(methodName)){
                var method = trait_[methodName];
                if((typeof method == 'function') && 
                    (typeof reciever[methodName] == 'function') &&
                    (method.toString().indexOf(parentName) > -1)) {
                    var baseMethod = reciever[methodName];
                    reciever[methodName] = function(){
                        var baseSaved = this[parentName];
                        this[parentName] = baseMethod;
                        var result = method.apply(this, arguments);
                        this[parentName] = baseSaved;
                        return result;
                    };
                }
                else {
                    reciever[methodName] = method;
                }
            }
        }
    }
    function mixinTrait (reciever) {
        for(var i = 0, len = traits.length; i < len; i++){  
            _trait(reciever, traits[i], 'super');
        }
    }
    function Constructor(){
        konstructor.apply(this, arguments);
        mixinTrait(this);
    }
    for(var key in konstructor.prototype){
        if(konstructor.prototype.hasOwnProperty(key)) Constructor.prototype[key] = konstructor.prototype[key];
    }
    mixinTrait(Constructor.prototype);
    return Constructor;
}

function BasicIntQueue(name){
    this.name = name;
    this._buf = [];
}
BasicIntQueue.prototype.get = function(){
    return this._buf.shift();
};
BasicIntQueue.prototype.put = function(x){
    this._buf.push(x);
};
function BasicIntQueue2(name){
    this.name = name;
    this._buf = [];

    this.get = function(){
        return this._buf.shift();
    };

    this.put = function(x){
        this._buf.push(x);
    };
}

var trait_Doubling = {
    put: function(x){
        this.super(2 * x);
    }
};
var trait_Incrementing = {
    put: function(x){
        this.super(x + 1);
    }
};
var trait_Filtering = {
    put: function(x){
        if(x >= 0) this.super(x);
    }
};

var Klass = trait(BasicIntQueue2, trait_Doubling, trait_Incrementing, trait_Filtering);
var queue = new Klass('Klass');
var queue1 = new BasicIntQueue('BasicIntQueue');

queue1.put(-1);

queue.put(-1);
queue.put(0);
queue.put(1);

console.log(queue.get()); // 2
console.log(queue.get()); // 4
console.log(queue.get()); // undefined
阅读 2.7k

超2真人
关注web前端开发,js,iOS等。 爱好历史、动漫等。

关注设计、漫画、动画,前端、javascript、iOS还有任何好玩的事情

1.1k 声望
104 粉丝
0 条评论
你知道吗?

关注设计、漫画、动画,前端、javascript、iOS还有任何好玩的事情

1.1k 声望
104 粉丝
宣传栏