JavaScript中的私有继承

时间:2014-03-28 20:23:43

标签: javascript inheritance prototype

使用访问说明符publicprotectedprivate指定C ++中的继承。私有继承使基类的公共成员和受保护成员成为派生类的私有成员。

有没有办法在JavaScript中实现私有继承?

我知道JavaScript有基于原型的继承,所以如果有办法让基类的公共成员成为派生类的私有成员,我感到很困惑。

3 个答案:

答案 0 :(得分:1)

这演示了C ++风格的“公共”,“受保护”和“私有”数据成员和成员函数。

function Base() {
  'use strict';
  /*--------------------------------------------------------------------------*/
  /*Declare all data members here using 'this.' which makes them 'public', but
  only in the scope of Base.                                                  */
  function Core() {
    this.private_data1 = 'private data1 of Base';
    this.private_data2 = 'private data2 of Base';
    this.protected_data1 = 'protected data1 of Base';
    this.protected_data2 = 'protected data2 of Base';
    this.public_data1 = 'public data1 of Base';
    this.public_data2 = 'public data2 of Base';
  }
  /*--------------------------------------------------------------------------*/
  /*Declare all member function here using 'Core.prototype.' which makes them
  'public' too, but again only in the scope of Base.                          */
  Core.prototype.private_function1 = function() {
    console.log('private function1 of Base.');
  };
  Core.prototype.private_function2 = function() {
    console.log('private function2 of Base.');
  };
  Core.prototype.protected_function1 = function() {
    console.log('protected function1 of Base.');
  };
  Core.prototype.protected_function2 = function() {
    console.log('protected function2 of Base.');
  };
  Core.prototype.public_function1 = function() {
    console.log('public function1 of Base.');
    /*We can call public, protected and private functions ...*/
    this.protected_function1();
    this.private_function1();
    /*... and access public, protected and private from here ...*/
    console.log(this.public_data1);
    console.log(this.protected_data1);
    console.log(this.private_data1);
    /*... even if they're overloaded.*/
    this.public_function2();
    this.protected_function2();
    this.private_function2();
    console.log(this.public_data2);
    console.log(this.protected_data2);
    console.log(this.private_data2);
  };
  Core.prototype.public_function2 = function() {
    console.log('public function2 of Base.');
  };
  /*--------------------------------------------------------------------------*/
  /*Define visibility of the members. If you're editing the core, make sure that
  each member is listed in no more and no less than one of these three
  functions.*/
  Core.prototype.grandPublicAccessTo = function(instance) {
    instance.public_data1 = mCore.public_data1;
    instance.public_data2 = mCore.public_data2;
    instance.public_function1 = function() { mCore.public_function1(); }
    instance.public_function2 = function() { mCore.public_function2(); }
  }
  Core.prototype.grandProtectedAccessTo = function(instance) {
    this.grandPublicAccessTo(instance);
    instance.protected_data1 = mCore.protected_data1;
    instance.protected_data2 = mCore.protected_data2;
    instance.protected_function1 = function() { mCore.protected_function1(); }
    instance.protected_function2 = function() { mCore.protected_function2(); }
  }
  Core.prototype.grandPrivateAccessTo = function(instance) {
    this.grandProtectedAccessTo(instance);
    instance.private_data1 = mCore.private_data1;
    instance.private_data2 = mCore.private_data2;
    instance.private_function1 = function() { mCore.private_function1(); }
    instance.private_function2 = function() { mCore.private_function2(); }
  }
  /*--------------------------------------------------------------------------*/
  var mCore = new Core();

  this.inherit = function(heir, core) {
    /*Grand the base core access to every member of heir's core, and ... */
    core.grandPrivateAccessTo(mCore);
    /*... grand the heir's core access to public and protected members of the
    base's core.*/
    mCore.grandProtectedAccessTo(heir);
  }

  /*Grand public access to every instance of Base.*/
  mCore.grandPublicAccessTo(this);
};

function Child() {
  'use strict';
  /*--------------------------------------------------------------------------*/
  /*Declare a few data members to demonstrate that these mask the corresponding
  members of Base.*/
  function Core() {
    this.private_data2 = 'private data2 of Child';
    this.protected_data2 = 'protected data2 of Child';
    this.public_data2 = 'public data2 of Child';
  }
  /*Overload some member functions to demonstrate that too.*/
  Core.prototype.private_function2 = function() {
    console.log('private function2 of Child.');
  };
  Core.prototype.protected_function2 = function() {
    console.log('protected function2 of Child.');
  };
  Core.prototype.public_function2 = function() {
    console.log('public function2 of Child.');
  };
  /*--------------------------------------------------------------------------*/
  /*Define visibility of the members. If you're editing the core, make sure that
  each member is listed in no more and no less than one of these three
  functions.*/
  Core.prototype.grandPublicAccessTo = function(instance) {
    instance.public_data2 = mCore.public_data2;
    instance.public_function2 = function() { mCore.public_function2(); }
  }
  Core.prototype.grandProtectedAccessTo = function(instance) {
    this.grandPublicAccessTo(instance);
    instance.protected_data2 = mCore.protected_data2;
    instance.protected_function2 = function() { mCore.protected_function2(); }
  }
  Core.prototype.grandPrivateAccessTo = function(instance) {
    this.grandProtectedAccessTo(instance);
    instance.private_data2 = mCore.private_data2;
    instance.private_function2 = function() { mCore.private_function2(); }
  }
  /*--------------------------------------------------------------------------*/
  var mCore = new Core();

  /*Inherit from Base. Multiple inheritance is possible.*/
  var base = new Base();
  base.inherit(this, mCore);

  /*Grand public access to every instance of Child.*/
  mCore.grandPublicAccessTo(this);
};

function main() {
  'use strict';

  console.log('testing base');
  var base = new Base();
  base.public_function1();
  /*Thinks like this:
  base.private_function1();
  would result in a TypeError.*/

  console.log('testing child');
  var child = new Child();
  child.public_function1();
}
main();                                                    

输出:
测试基地
基地的公共功能1 保护功能1的基础。
基地的私人功能1 基地公共数据1 基数的受保护数据1 基地的私人数据1 基地的公共功能2 Base的受保护功能2 基地的私人功能2 基地公共数据2 基数的受保护数据2 基地的私人数据2 测试孩子
基地的公共功能1 保护功能1的基础。
基地的私人功能1 基地公共数据1 基数的受保护数据1 基地的私人数据1 儿童的公共功能2 儿童的受保护功能2 儿童的私人功能2 儿童的公共数据2 儿童的受保护数据2 儿童的私人数据2

答案 1 :(得分:0)

在派生类构造函数调用基类构造函数的位置继承基类的实例属性。此时,需要继承的基类的所有实例属性 privately 可以作为局部变量存储在派生类的构造函数中,并随后从派生类的实例。

这种技术显然不适用于从基类原型继承的属性。然而,这适用于我的用例,因此我在这里分享它。

在下面的示例中,派生类ChocolateCake 私有 从基类setBakingTemperature继承成员Cake。< / p>

function Cake() {
    var bakingTemperature = 250;
    this.setBakingTemperature = function(temperature) {
        bakingTemperature = Math.min(temperature, 400);
    }
    this.getBakingTemperature = function() {
        return bakingTemperature;      
    }
}

Cake.prototype.bake = function() {
    console.log("Baking the cake at " + this.getBakingTemperature() + " °C");
}

function ChocolateCake() {
    Cake.call(this);

    /* inherit 'setBakingTemperature' privately */
    var setBakingTemperature = this.setBakingTemperature;
    delete this.setBakingTemperature;

    setBakingTemperature(300);
}

ChocolateCake.prototype = Object.create(Cake.prototype, {
    constructor: {value: ChocolateCake}
});


var chocolateCake = new ChocolateCake();
chocolateCake.setBakingTemperature(); /* throws TypeError exception */
chocolateCake.getBakingTemperature(); /* 300 */
chocolateCake.bake(); /* Baking the cake at 300 °C */

更新:

使用@ p.kamps的想法,还有另一种方法可以实现这一目标。这种方法的优点是子类可以选择要从基类继承的属性,而不需要关心其他属性。

var Cake = function() {
    var bakingTemperature = 250;
    var setBakingTemperature = function(temperature) {
        bakingTemperature = Math.min(temperature, 400);
    }
    this.inheritSetBakingTemperature = function() {
        if (this instanceof Cake) {
            return setBakingTemperature;
        }
        return null;
    }
    this.getBakingTemperature = function() {
        return bakingTemperature;
    }
}

Cake.prototype.bake = function() {
    console.log("Baking the cake at " + this.getBakingTemperature() + " °C");
}

var ChocolateCake = function() {
    Cake.call(this);

    /* inherit 'setBakingTemperature' privately */
    var setBakingTemperature = this.inheritSetBakingTemperature();

    setBakingTemperature(300);
}

ChocolateCake.prototype = Object.create(Cake.prototype, {
    constructor: {value: ChocolateCake}
});

var chocolateCake = new ChocolateCake();
chocolateCake.setBakingTemperature(); /* throws TypeError exception */
chocolateCake.getBakingTemperature(); /* 300 */
chocolateCake.bake(); /* Baking the cake at 300 °C */

答案 2 :(得分:-1)

JavaScript中任何对象的私有成员都在函数中定义,该函数将对象本身创建为函数的变量,因此这些变量只能在引用变量的对象的方法中可见,这要归功于Clousure

function Person (age) {
  var age = age;
  this.name = 'Robert';
  this.isAdult = function () {
    return age > 17;
  };
}

在上面的代码中,年龄属性&#39;它是私有的,非常私密,实际上无法修改,你唯一可以做的就是用isAdult方法检查它是否大于17。

在SubClass构造函数中实现它几乎是一回事,你只需要定义原型的属性,你就不能将private作为构造函数中的变量来定义,并定义对象的方法。也可以在构造函数中访问该属性。