js的对象可以从类的原型对象中继承属性。如果O是类B的实例,B是A的子类,那么O也一定从A中继承了属性。为此首先要确保B的原型对象继承自A的原型对象。通过inherit()函数,可以这样来实现:
B.prototype = inherit(A.prototype); //子类派生自父类 参见前几章的介绍
B.prototype.constructor = B; //重载继承来自constructor属性
这两行代码是在js中创建子类的关键。如果不这样做,原型对象仅仅是一个普通对象,它只继承自Object.prototype。
例:定义子类
//用一个简单的函数创建简单的子类
function defineSubclass(superclass /*参数 父类构造函数*/,constructor /*参数 新子类的构造函数*/,methods/*实例方法:复制至原型中*/,statics /*参数 类属性:复制至构造函数中*/){
//建立原型对象
constructor.prototype = inherit(superclass.prototype);
constructor.prototype.constructor = constructor;
//对象常规类一样复制方法和类属性
if(methods) extend(constructor.prototype,methods);
if(statics) extend(constructor,statics);
return constructor;
}
//也可以通过父类构造函数的方法来做到这一点
Functon.prototype.extend= function(constructor,methods,statics){
return defineSubclass(this, constructor,methods,statics);
}
SingletonSet:一个简单的子类
function SingletonSet(member){
this.member = member; //记住集合中这个唯一的成员
}
//创建一个原型对象,这个原型对象继承自Set的原型
SingletonSet.prototype = inherit(Set.prototype);
//给原型添加属性
//如果有同名的属性就覆盖Set.prototype中的同名属性
Extend(SingletonSet.prototype,{
//设置合适的constructor属性
consructor:SingletonSet,
add:function(){
throw “read-only set”;
},
remove:function(){
throw “read-only set”;
},
Size:function(){return 1;},
foreach:function(f,context){
f.call(context,this.member);
},
contains:function(x){return x===this.member;}
});
它包含5个简单的方法定义,它实现了5个核心的Set方法,但从它的父类中继承的 toString()/toArray()和equals()方法,定义子类就是为了继承这些方法,比如,Set类的equals()方法用来实现Set实例进行比较,只要Set实例包含size()和foreach()方法,就可以通过equals()比较。因为SingletonSet是Set的子类,所以它自动继承了equals()的实现,不用再实现一次。当然,如果想要最简单的实现方式,那么给SingletonSet类定义自己的equals()版本会更高效些:
SingletonSet.prototype.equals = function(that){
return that instanceof Set&& that.size()==1 && that.contains(this.member);
};
需要注意的是,SingletonSet不是将Set中的方法列表静态地借用过来,而是动态地从Set类继承方法。如果Set.prototype添加新的方法,Set和SingletonSet的所有实例就会立即拥有这个方法。