不止一次地继承,每个实例保持成员私有

时间:2011-10-11 08:18:58

标签: javascript oop inheritance

基本上,我正在尝试做的事情,已经多次讨论过了。但是,大多数示例仅包含继承自ClassB的ClassA。我的情况非常简单,但似乎没有在我找到的JavaScript主题中解决。

ClassB扩展了ClassA,它有一个成员。 ClassC和ClassD扩展了ClassB。但是,在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关键字创建的单独实例,因此不应该共享成员。有人可以解释一下吗?

可以从ClassA中删除_construct()函数,但不起作用。 可以删除var This = this行,并且This的所有后续引用都可以更改为this,但不起作用。

1 个答案:

答案 0 :(得分:0)

你需要在每个班级中调用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不是跨实例共享的。