特质(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