以下のコードがあるとしましょう:
function A() {
function modify(){
x = 300;
y = 400;
}
var c = new C();
}
function B() {
function modify(){
x = 3000;
y = 4000;
}
var c = new C();
}
C = function () {
var x = 10;
var y = 20;
function modify() {
x = 30;
y = 40;
};
modify();
alert("The sum is: " + (x+y));
}
ここで問題は、Cのメソッドmodify
をAおよびBのメソッドでオーバーライドできる方法があるかどうかです。Javaではsuperキーワードを使用しますが、 JavaScriptでこのようなことをどのように達成できますか?
編集:元の答えが書かれてから6年が経ち、多くが変わりました!
幸運を!
JavaScriptの継承は、Javaとは少し異なります。ネイティブJavaScriptオブジェクトシステムの外観は次のとおりです。
// Create a class
function Vehicle(color){
this.color = color;
}
// Add an instance method
Vehicle.prototype.go = function(){
return "Underway in " + this.color;
}
// Add a second class
function Car(color){
this.color = color;
}
// And declare it is a subclass of the first
Car.prototype = new Vehicle();
// Override the instance method
Car.prototype.go = function(){
return Vehicle.prototype.go.call(this) + " car"
}
// Create some instances and see the overridden behavior.
var v = new Vehicle("blue");
v.go() // "Underway in blue"
var c = new Car("red");
c.go() // "Underway in red car"
残念ながら、これは少し見苦しく、「スーパー」への非常に良い方法は含まれていません。どの親クラスのメソッドを呼び出すかを手動で指定する必要があります。その結果、クラスの作成をより良くするためのさまざまなツールがあります。 Prototype.js、Backbone.js、またはjsでOOPを実行するためのより良い構文を含む同様のライブラリを見てみてください。
これはGoogleのトップヒットであるため、最新の回答を提供したいと思います。
ES6クラス を使用すると、継承とメソッドのオーバーライドがはるかに簡単になります。
'use strict';
class A {
speak() {
console.log("I'm A");
}
}
class B extends A {
speak() {
super.speak();
console.log("I'm B");
}
}
var a = new A();
a.speak();
// Output:
// I'm A
var b = new B();
b.speak();
// Output:
// I'm A
// I'm B
super
キーワード は、継承クラスで使用される場合、親クラスを参照します。また、親クラスのすべてのメソッドは子のインスタンスにバインドされているため、super.method.apply(this);
を記述する必要はありません。
互換性に関しては、 ES6互換性テーブル は、主要なプレーヤーサポートクラス(ほとんど)の最新バージョンのみを示しています。 V8ブラウザーは今年の1月(ChromeとOpera)からこれらを使用しており、SpiderMonkey JSエンジンを使用するFirefoxは来月、公式のFirefox 45リリースでクラスを見ることになります。モバイル側では、Androidはまだこの機能をサポートしていませんが、5か月前にリリースされたiOS 9は部分的にサポートしています。
幸いなことに、HarmonyコードをES5コードに再コンパイルするためのJSライブラリである Babel があります。クラス、およびES6のその他の多くのクールな機能により、Javascriptコードをより読みやすく、保守しやすくすることができます。
古典的なOOをエミュレートすることは避け、代わりにプロトタイプのOOを使用してください。プロトタイプのOO用のNiceユーティリティライブラリは traits です。
メソッドを上書きして継承チェーンを設定するのではなく(オブジェクトの継承よりも常にオブジェクトの合成を優先する必要があります)、再利用可能な関数を特性にバンドルし、それらを使用してオブジェクトを作成する必要があります。
var modifyA = {
modify: function() {
this.x = 300;
this.y = 400;
}
};
var modifyB = {
modify: function() {
this.x = 3000;
this.y = 4000;
}
};
C = function(trait) {
var o = Object.create(Object.prototype, Trait(trait));
o.modify();
console.log("sum : " + (o.x + o.y));
return o;
}
//C(modifyA);
C(modifyB);
この例のmodify()はプライベート関数であり、A、B、またはC定義内以外のどこからもアクセスできません。次のように宣言する必要があります
this.modify = function(){}
Cは、Cに渡さない限り、親への参照を持ちません。CがAまたはBから継承するように設定されている場合、パブリックメソッドを継承します(modify()が定義されているようなプライベート関数ではありません)。 Cが親からメソッドを継承すると、継承されたメソッドをオーバーライドできます。
modify()
をオーバーライドする場合、最後に呼び出したmodify()
メソッドはグローバルコンテキストで呼び出されます。最初にA
またはB
を継承する必要があります。
たぶんあなたはこれをやろうとしている:
この場合、C
はA
を継承します
function A() {
this.modify = function() {
alert("in A");
}
}
function B() {
this.modify = function() {
alert("in B");
}
}
C = function() {
this.modify = function() {
alert("in C");
};
C.prototype.modify(); // you can call this method where you need to call modify of the parent class
}
C.prototype = new A();
すべての変数を「公開」しない限り、つまり、直接またはFunction
プロパティを介してprototype
のメンバーにする必要はありません。
var C = function( ) {
this.x = 10 , this.y = 20 ;
this.modify = function( ) {
this.x = 30 , this.y = 40 ;
console.log("(!) C >> " + (this.x + this.y) ) ;
} ;
} ;
var A = function( ) {
this.modify = function( ) {
this.x = 300 , this.y = 400 ;
console.log("(!) A >> " + (this.x + this.y) ) ;
} ;
} ;
A.prototype = new C ;
var B = function( ) {
this.modify = function( ) {
this.x = 3000 , this.y = 4000 ;
console.log("(!) B >> " + (this.x + this.y) ) ;
} ;
} ;
new C( ).modify( ) ;
new A( ).modify( ) ;
new B( ).modify( ) ;
いくつかの変更があります。
最も重要なのは、想定される「スーパークラス」コンストラクターの呼び出しが、この行内で暗黙的に行われるようになったことです。
<name>.prototype = new C ;
A
とB
の両方に個別に変更可能なメンバーx
とy
が追加されました。これは、代わりに... = C
と書いた場合には当てはまりません。
次に、x
、y
、およびmodify
はすべて「パブリック」メンバーであるため、異なるFunction
を割り当てる
<name>.prototype.modify = function( ) { /* ... */ }
その名前で元のFunction
を「オーバーライド」します。
最後に、modify
宣言でFunction
の呼び出しを行うことはできません。これは、想定される「サブクラス」のprototype
プロパティに想定される「スーパークラス」を設定すると、「スーパークラス」の暗黙的な呼び出しが再度実行されるためです「。
しかし、まあ、これはJavaScriptでこの種のことを多かれ少なかれ行う方法です。
HTH、
FK
function A() {
var c = new C();
c.modify = function(){
c.x = 123;
c.y = 333;
}
c.sum();
}
function B() {
var c = new C();
c.modify = function(){
c.x = 999;
c.y = 333;
}
c.sum();
}
C = function () {
this.x = 10;
this.y = 20;
this.modify = function() {
this.x = 30;
this.y = 40;
};
this.sum = function(){
this.modify();
console.log("The sum is: " + (this.x+this.y));
}
}
A();
B();