C++中的繼承是通過訪問說明符public
,protected
和private
指定的。私有繼承使得基類的public和protected成員成爲派生類的私有成員。JavaScript中的私有繼承
有什麼辦法在JavaScript中實現私有繼承?
我知道JavaScript有基於原型的繼承,所以我很困惑如果有一種方法可以讓基類的公共成員成爲派生類的私有成員。
C++中的繼承是通過訪問說明符public
,protected
和private
指定的。私有繼承使得基類的public和protected成員成爲派生類的私有成員。JavaScript中的私有繼承
有什麼辦法在JavaScript中實現私有繼承?
我知道JavaScript有基於原型的繼承,所以我很困惑如果有一種方法可以讓基類的公共成員成爲派生類的私有成員。
JavaScript中任何對象的私有成員都是在創建對象本身作爲函數變量的函數中定義的,因此這些變量只會在引用變量的對象的方法中可見,這要歸功於Clousure。
function Person (age) {
var age = age;
this.name = 'Robert';
this.isAdult = function() {
return age > 17;
};
}
在上面的代碼中,年齡「財產」是私有的,所以私人它實際上不能被修改,你可以用它做的唯一的事情就是檢查它是否大於17的isAdult方法。
在SubClass構造函數中實現它幾乎是一回事,你只需要定義你想在構造函數中將私有變量作爲變量的原型屬性,並定義將會也可以在構造函數中訪問該屬性。
'prototype'的每個屬性都可以通過子類的任何實例公開訪問。我們不能用'prototype'屬性來做到這一點。 –
基類的實例屬性在派生類構造函數調用基類構造函數的地方繼承。此時,需要繼承的基類的所有實例屬性都可以作爲局部變量存儲在派生類的構造函數中,然後從派生類的實例中刪除。
這種技術顯然不適用於從基類原型繼承的屬性。然而,這個服務於我的用例,因此我在這裏分享它。
在下面的例子中,派生類ChocolateCake
私下繼承從基類Cake
構件setBakingTemperature
。
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 */
這演示了C++風格的「public」,「protected」和「private」數據成員和成員函數。
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。
Base的受保護功能1。
Base的私有函數1。
基地
基地
基地的私人數據1
基地公共函數2的保護數據1的公共數據1。
Base的受保護功能2。
Base的私有函數2。
基地
基地
基地
測試孩子的私人數據2
基地的公共功能1的保護數據2的公開數據2。
Base的受保護功能1。
Base的私有函數1。
基地
基地
基地的私人數據1
兒童的公共函數2的保護數據1的公共數據1。
Child的保護功能2。
Child的私人功能2。
兒童
保護兒童
兒童
參考'Base'的'inherit'方法,爲什麼你想讓基類的核心'私有'訪問派生類的核心,基類不應該不知道派生它的類? –
你的解決方案看起來很乾淨,但我們只是處理實例屬性,所以不使用基於'prototype'的繼承。你能告訴我在每個課程中引入「核心」的動機嗎?我的意思是,每個階級都可以首先讓每個「公共」成員直接暴露,並將每個其他成員都設爲「私人」或「受保護」作爲私有變量。另外,每個類都可以暴露一個方法,讓其他類可以暴露這個類的'protected'成員。 –
@Bharat Khatri:The Base使用派生的核心來啓用基礎的派生重載方法。沒有這個,最後的6行輸出將會不同。 –
我不的私人數據2的數據2的公開數據2認爲是可能的。 – pj013
JavaScript沒有訪問修飾符的概念。所以不,不可能。 – Bart
http://stackoverflow.com/questions/3617139/private-variables-in-inherited-prototypes - 已經回答 – pj013