class Task { id; // 构造函数 Task() Task(ID) {id = ID;} outputTask() {output(id);} } class XYZ inherits Task { label; XYZ(ID, Lable){ super(ID); label = Label; } outputTask() { super(); output(label) } }
class ABC inherits Task { //... }
Task 是通用父类,XYZ,ABC 是子类,继承 Task。类设计模式鼓励你在继承时使用方法重写,甚至在添加新行为时通过 super 调用这个方法的原始版本。许多方法可以先抽象到父类然后再用子类进行特殊化。可以实例化子类 XYZ 的一些副本然后使用这些实例来执行任务 XYZ。这个实例会复制 Task 定义的通用行为以及 XYZ 定义的特殊行为。同理,ABC 类的实例也会复制 Task 的行为和 ABC 的行为。
Task = { setID: function(ID) { this.id = ID; } outputID: function(){ console.log(this.id); } }; // 让 XYZ 委托 Task XYZ = Object.create(Task); XYZ.prepareTask = function(ID, Label) { this.setID( ID ); this.label = Label; } XYZ.outputTaskDetails = function() { this.outputID(); console.log( this.label ); }; // ABC = Object.create( Task ); // ABC ... = ...
在这段代码中,Task 和 XYZ 并不是类或者函数,它们是对象。 XYZ 通过 Object.create(...) 创建,它的 [[Prototype]] 委托了 Task 对象。
相比于类或者说面向对象,我会把这种编码风格称为 “对象关联”。我们真正关心的只是 XYZ 对象委托了 Task 对象
1、id 和 label 都是直接存储在 XYZ 上而不是 Task 上 2、在类设计中,父类和子类利用同样的方法重写,委托行为中则恰恰相反,尽量避免不同级别使用相同的命名 3、setID 方法在 XYZ 中没有找到,通过 [[Prototype]] 委托关联到 Task 继续寻找,找到了,由于调用位置触发了 this 隐式绑定规则,这个 this 仍然会绑定到 XYZ的,这正是我们想要