クラス指向言語とは対照的に、JSはプロトタイプベースであり、オブジェクトのコンストラクタは "コンストラクタロジック"(私はこの用語をMDNで見つけました)だけでなく、特権メソッドも定義します。 1つの "クラス"が別のクラスの子である場合(残念ですが、私はJSの "クラス"よりも良い言葉がわかりません)、これは子クラスがオーバーライドする前に親コンストラクタが実行されるかまたはコンストラクタがまだ実行されていないため、子クラスはメソッドをオーバーライドできません。Javascript:子クラスの継承されたメソッドをオーバーライドした後、親クラスのコンストラクタロジックを実行するにはどうすればよいですか?
私が意味するものを説明するための例を挙げます。オブジェクトの特権関数を定義する「親クラス」と、このメソッドを呼び出すコンストラクタロジックを想定します。
function Parent() {
this.methodA = function() {
// do something
};
// C'tor logic starts here
// Beside other things also call some method of this object
this.methodA();
}
はmethodA
を再定義するが、それでも親クラスのコンストラクタ ロジックを使用しなければならない子クラスを想定します。
最初のアプローチは、子コンストラクタ の先頭に親コンストラクタを呼び出すことです。しかし、親コンストラクタは依然として親の 実装を呼び出します。
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
function Child() {
// Call parent constructor first. Problem: The parent constructor
// calls methodA before it will be overriden by child constructor
Parent.call(this);
var _oldMethodA = this.methodA;
this.methodA = function() {
// do something special and then call parent method
_oldMethodA.call(this);
};
}
第2のアプローチは、親メソッドをオーバーライドすることができない 後、しかし、その後、親のコンストラクタを呼び出すことです。特権メソッドの定義とコンストラクタロジック - - 正しい順序で呼び出されていますか?私はJSコンストラクタの両方のタスクをインターリーブするにはどうすればよい
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
function Child() {
// Override first. Problem: The parent constructor has not defined methodA
// yet, hence the line below fails.
var _oldMethodA = this.methodA;
this.methodA = function() {
// do something special and call parent method
_oldMethodA.call(this);
};
Parent.call(this);
}
付録
- 追加の材料によるコメント
に私は私が欲しいものを明確にすることがないようだというコメントから考え出しました。そこでここではこれは次の出力
$> I do the work of the parent's method
$> I do the work of the child's method and ...
$> I do the work of the parent's method
これは何が起こるかになり
class Parent {
public Parent() {
methodA();
}
public void methodA() {
System.out.println("I do the work of the parent's method");
}
}
class Child extends Parent {
public Child {
super();
}
public void methodA() {
System.out.println("I do the work of the child's method and ...");
super();
}
}
Parent p = new Parent();
Child c = new Child();
のJava
で書かれた例があります。Parent
のコンストラクタは、
Parent
で定義された
methodA
の実装を呼び出します。これは特別なものではなく、最初の出力行を生成します。
Child
のコンストラクタは、前と同じように
methodA
を再度呼び出す親のコンストラクタを呼び出します。しかしながら、これは親のコンストラクタであるが、オブジェクトは依然として
Child
のインスタンスであるため、子クラスの
methodA
の実装が実行される。このメソッドは、2行目の出力を出力し、3行目を生成する親のメソッドを明示的に呼び出します。
これはOOPによると完全な正しい動作であり、これはJavascriptでも達成したいものです。実際はopposite of the problem mentioned hereです。リンクはコメントのものです。
どこ 'methodB'はありますか? – Ben
あなたの問題は、プロトタイプベースの継承や特権メソッドではなく、コンストラクタからオーバーライド可能なメソッドを呼び出すことにあります。それは私が見たどの言語でもうまくいきません。 – Bergi
@BenAston:申し訳ありませんが、 'methodB'はコメントの入力ミスです。以前のバージョンの例では2つのメソッドを使用しましたが、MWEを1つのメソッドに煮詰めました。 – user2690527