在我的项目中,我使用JavaScript原型来实现继承。我有一个超级类型(如汽车)和许多子类型(奥迪/梅赛德斯/ ...)。每个汽车品牌都在使用' Horn'这是一个非常庞大的类型,不应该重复。这种类型的一种方法应该被每个汽车品牌覆盖,但应该只存在于特定子类型的范围内。如果不为每个汽车子类型创建一个Horn子类型,这是否可行? 谢谢!
http://codepen.io/trek7/pen/QGYaBW
function Horn() {
this.level = '123dB';
}
Horn.prototype.doTutut = function() {
return "Düdelüüüü!";
};
/********************************************/
function Car() {
this.horn = new Horn();
}
Car.prototype.honk = function() {
return this.horn.doTutut();
};
/********************************************/
Mercedes.prototype = new Car();
function Mercedes() {
this.color = 'blue';
}
Mercedes.prototype.drive = function() {
return "...BrumBrum...";
};
/********************************************/
Audi.prototype = new Car();
function Audi() {
this.color = 'red';
/* BAD Overwrite, but how can I achieve this functionality
without creating another Horn subtype? */
Horn.prototype.doTutut = function() {
return "Tütütütütü!";
};
}
Audi.prototype.honk = function() {
return this.horn.doTutut();
};
/********************************************/
var car = new Car();
car.honk(); // Düdelüüüü! - Right!
var mercedes = new Mercedes();
mercedes.honk(); // Düdelüüüü! - Right!
var audi = new Audi();
audi.honk(); // Tütütütütü! - Right!
mercedes.honk(); // Tütütütütü! - Wrong!
答案 0 :(得分:1)
这里常见的事情是参数化 Horn
类,以便它接受要发出的声音:
function Horn(sound) {
this.sound = sound !== undefined ? sound : "Düdelüüüü!";
this.level = '123dB';
}
Horn.prototype.doTutut = function() {
return this.sound;
};
然后在Mercedes
内,你要么将声音传递给Car
超级构造函数,要么在this.horn
之后设置它。
如果您需要重写整个方法,可以将其分配给this.horn.theMethod
:
function Mercedes() {
Car.call(this); // See below, important to do this first
this.horn.theMethod = function() {
// New implementation here
};
}
...但是首先修复下面的继承内容非常重要。
当然,如果您希望所有Mercedes
个实例(例如)共享单个 Horn
实例,只需在{{1 }}
旁注:您的继承设置使用了经常重复的反模式。不要这样做:
Mercedes.prototype
如果你这样做,有两个问题:
Mercedes.prototype = new Car();
无法接受参数,
Car
错误
因为Mercedes.prototype.constructor
将对象(Car
)分配给new Horn
,所以每个子类的所有实例(this
,{ {1}}等)最终共享相同的对象(一个号角)。如果那个对象是无状态的,那很好,但它应该在Mercedes
上。如果它不是无状态的,则会在Audi
个实例之间产生难以诊断的串扰。
此外,Car.prototype
永远不会调用Car
,它应该为Mercedes
提供初始化实例部分的机会。
在ES5中,这是正确的方法:
Car
当然,在ES2015及以上版本中(您现在可以使用它进行转换),它只是:
Car
...除非function Mercedes() {
// Gives `Car` its chance to do init; could pass on args here if appropriate
Car.call(this);
this.color = 'blue';
}
// Set up the prototype chain
Mercedes.prototype = Object.create(Car.prototype);
Mercedes.prototype.constructor = Mercedes;
Mercedes.prototype.drive = function() {
return "...BrumBrum...";
};
构造函数接受参数class Mercedes extends Car {
drive() {
return "...BrumBrum...";
}
}
不需要/使用。
这是一个更新的继承和跨所有子类实例的共享号角的示例:
Mercedes