在正式版中本部分代码会有较大的改变,但是对this.parent在Opera下的实现仍然不尽人意,在子类的同名方法中使用非完整路径的对象时会有问题,目前想到的解决方法是把这部分代码单独提出到一个方法中调用
JAVASCRIPT:
/*
作为内置类型的Class,使JS的优雅OOP成为可能
因为1519版本有bug,所以以1543版代码为例
*/
var Class = new Native({
//族名,为$type提供精准类型判断
name: 'Class',
//JS way的构造函数,始于Prototype?
initialize: function(properties){
properties = properties || {};
//真正用于返回的类的原型
var klass = function(empty){
//复制前先解除关联
for (var key in this) this[key] = $unlink(this[key]);
//复制Class.Mutators的方法,使新类支持实现和继承
for (var mutator in Class.Mutators){
if (!this[mutator]) continue;
Class.Mutators[mutator](this, this[mutator]);
//已使用,移除
delete this[mutator];
}
this.constructor = klass;
//给构造函数传空函数时直接返回,不作后续处理
if (empty === $empty) return this;
//对于类本身的构造函数,将参数原样传递
var self = (this.initialize) ? this.initialize.apply(this, arguments) : this;
//对于参数中的方法,直接执行,不传递参数
if (this.options && this.options.initialize) this.options.initialize.call(this);
return self;
};
//将Class的特性复制给klass,相当于让klass继承Class
$extend(klass, this);
klass.constructor = Class;
//指定原型
klass.prototype = properties;
return klass;
}
});
//使用继承自Native的implement方法,让新的implement覆盖之
Class.implement({
implement: function(){
Class.Mutators.Implements(this.prototype, Array.slice(arguments));
return this;
}
});
Class.Mutators = {};
/*
使类支持Implements的写法实现
var myClass = new Class({
Implements : [Events, Options],
...
});
*/
Class.Mutators.Implements = function(self, klasses){
//$splat使支持多个Implements
$splat(klasses).each(function(klass){
$extend(self, ($type(klass) == 'class') ? new klass($empty) : klass);
});
};
/*
使类支持Extends的写法继承
var myClass = new Class({
Extends : Base,
...
});
*/
Class.Mutators.Extends = function(self, klass){
klass = new klass($empty);
for (var property in klass){
var kp = klass[property];
var sp = self[property];
self[property] = (function(previous, current){
//继承出现相同属性、方法时的处理
if ($defined(current) && previous != current){
var type = $type(current);
if (type != $type(previous)) return current;
switch (type){
case 'function':
return function(){
//继承出现同名方法时,this.parent可以引用到父类的同名方法
current.parent = this.parent = previous.bind(this);
var value = current.apply(this, arguments);
this.parent = current.parent;
return value;
};
case 'object': return $merge(previous, current);
default: return current;
}
}
return previous;
})(kp, sp);
}
};