Javascript:类设计模式 - 伪多态性



在Kyle Simpson的You-Don't-Know-Js系列丛书中,他在讨论该系列的ObjectPrototypes书中pre-es6 javascript中的类模式实现时,在第4章中提到了他所谓的伪多态性

他这样描述这种伪多态性:

但是由于JavaScript的特殊性,显式伪多态性(因为阴影!(在每个需要这种(伪(多态引用的函数中创建了脆弱的手动/显式链接。这会显著增加维护成本。此外,虽然显式伪多态性可以模拟"多重继承"的行为,但它只会增加复杂性和脆性。

根据我在这里的理解,这种伪多态性是一种不好的行为,我们最好避免,因为显式调用SUPER类,就像他关于从Car类内部调用Vehicle类的示例一样,因此我们将这样做作为显式调用,如下所示:

function Car () {
Vehicle.call( this );
}
//also overriding Vehicle's methods
Car.prototype.methodName = function( p1 ) {
//manipulate p1 then call the super method. 
Vehicle.prototype.methodName.call( this, p1 );
};

但我想知道这里的问题是否与车辆类名的显式使用有关,那么为什么我们不这样做:

function Car () {
this.super = Object.getPrototypeOf( this ).constructor;
this.super.call( this );
}
//also overriding Vehicle's methods
Car.prototype.methodName = function( p1 ) {
//manipulate p1 then call the super method. 
this.super.prototype.methodName.call( this, p1 );
};

这种伪造或模仿其他面向类语言的超级关键字来解决问题吗?

...为什么我们不这样做...

因为它不起作用,但你远不是第一个掉进陷阱的人。尝试添加CarLuxuryCar子类以查看问题:现在this.super(即使在Car代码中(指的是Car,而不是Vehicle

有一些模式可以避免在 ES5 级别的代码中显式使用Car中的名称Vehicle(我在 2009 年编写了其中一种(,但它们现在已经过时了;相反,我们使用 ES2015 中的class语法(必要时进行转译(:

class Vehicle {
methodName() {
console.log("Vehicle#methodName");
}
}
class Car extends Vehicle {
methodName() {
super.methodName();
console.log("Car#methodName");
}
}
class LuxuryCar extends Car {
methodName() {
super.methodName();
console.log("LuxuryCar#methodName");
}
}
const l = new LuxuryCar();
l.methodName();

最新更新