多次继承,使每个实例的成员保持私有

Inheriting more than once, keeping members private per instance

本文关键字:成员 实例 继承      更新时间:2023-09-26

基本上,我要做的是已经讨论过很多次的事情。然而,大多数示例只具有继承ClassB的ClassA。我的情况是相当微不足道的,但似乎没有解决在JavaScript主题,我发现。

ClassB继承了ClassA,后者有一个成员。类c和类d扩展类b。但是,当在ClassC的实例中设置唯一的成员时,该成员也在ClassD的成员中设置。让我们看一个例子:

function ClassA(data) {
        var This = this;
        This._data = {};
        This._construct = function(data) {
            if( undefined === data ) {
                This._data = {};
                return true;
            }
            This._data = data;
        }

        This._construct(data);
    }
    function ClassB() {
    }
    ClassB.prototype = new ClassA();
    ClassB.prototype.constructor = ClassB;
    function ClassC() { // Extends ClassB
    }
    ClassC.prototype = new ClassB();
    ClassC.prototype.constructor = ClassC;
    function ClassD() { // Extends ClassB
    }
    ClassD.prototype = new ClassB();
    ClassD.prototype.constructor = ClassD;

    var objectC = new ClassC();
    var objectD = new ClassD();
    objectC._data['somevar'] = 'asdasdasd';
    console.log(objectC._data); // Object { somevar="asdasdasd"}
    console.log(objectD._data); // Object { somevar="asdasdasd"}

如果你在console.log(objectC._data);上设置了一个断点,你可能会在FireBug的Watch窗口中看到所有的原型都设置正确了。这真的很奇怪,因为很明显ClassC和ClassD的原型是用new关键字创建的单独实例,因此不应该共享成员。有人能解释一下吗?

可以将_construct()函数从ClassA中移除,但没有效果。可以删除var This = this行,随后所有对This的引用都可以更改为this,没有影响。

您需要在每个类中调用super,以使此模式工作。你可以这样做。

//Simplifying the construction part a bit.
function ClassA(data) {
    this._data = data || {};
}
function ClassB(data) {
    ClassA.call(this, data); //call super class (ClassA) constructor
    //here you can initialize any ClassB specific variables
}
ClassB.prototype = new ClassA();
ClassB.prototype.constructor = ClassB;
function ClassC(data) { // Extends ClassB
    ClassB.call(this, data); //call super class (ClassB) constructor
    //here you can initialize any ClassC specific variables
}
ClassC.prototype = new ClassB();
ClassC.prototype.constructor = ClassC;
function ClassD(data) { // Extends ClassB
    ClassB.call(this, data); //call super class (ClassB) constructor
    //here you can initialize any ClassD specific variables
}
ClassD.prototype = new ClassB();
ClassD.prototype.constructor = ClassD;

var objectC = new ClassC();
var objectD = new ClassD();
objectC._data['somevar'] = 'asdasdasd';
console.log(objectC._data); // Object { somevar="asdasdasd"}
console.log(objectD._data); // Object {}  -- empty for objectD

现在您可以看到_data不是跨实例共享的。