では、クラスの継承・オーバーライド・super とアロー関数の関係を具体例で詳しく解説します。
ポイントは「プロトタイプメソッドとアロー関数ではオーバーライドの挙動が違う」ということです。
1. 基本:プロトタイプメソッドでの継承とオーバーライド
class Animal {
speak() { // プロトタイプ上のメソッド
console.log("Animal speaks");
}
}
class Dog extends Animal {
speak() { // オーバーライド
super.speak(); // 親のメソッド呼び出し
console.log("Dog barks");
}
}
const d = new Dog();
d.speak();
/* 出力:
Animal speaks
Dog barks
*/
JavaScript✅ ポイント
speakはプロトタイプ上にあるので、子クラスで上書き(オーバーライド)可能。super.speak()で親クラスの処理を呼べる。- 継承関係がきちんと保たれる。
2. アロー関数を使う場合(インスタンスプロパティとして定義)
class Animal {
speak = () => { // インスタンスごとのアロー関数
console.log("Animal speaks");
}
}
class Dog extends Animal {
speak = () => { // こちらもアロー関数
// super.speak(); // ❌ これはエラーになる
console.log("Dog barks");
}
}
const d = new Dog();
d.speak(); // Dog barks
JavaScript⚠️ 注意点
speakはプロトタイプ上ではなく、インスタンスごとのプロパティになっています。- そのため
super.speak()は呼べません(super はプロトタイプチェーンのメソッドを呼ぶため、インスタンスプロパティのアロー関数は対象にならない)。 - 「親の処理を呼びつつオーバーライド」したい場合はアロー関数ではなく、プロトタイプメソッド(通常のメソッド)を使う必要があります。
3. 実務的なまとめ
| 使い方 | オーバーライド | super呼び出し | 備考 |
|---|---|---|---|
| プロトタイプメソッド(普通のメソッド) | ✅ 可能 | ✅ 可能 | 継承との相性が良い |
| クラスフィールドのアロー関数 | ❌ できない | ❌ できない | 自動バインドは便利だが、継承して親処理呼ぶ場合には不向き |
4. 例:継承関係で親処理+イベントハンドラもやりたい場合
class Base {
constructor() { this.count = 0; }
log() { console.log("Base log", this.count); }
}
class Sub extends Base {
log() {
super.log(); // 親の log を呼べる
console.log("Sub log", this.count);
}
}
const s = new Sub();
s.count = 5;
s.log();
/* 出力:
Base log 5
Sub log 5
*/
JavaScript→ もし log をアロー関数で書くと、super.log() が使えないので親の処理を呼べなくなる。
→ 継承+親処理呼び出しが必要な場合は、必ずプロトタイプメソッドで定義する。
💡 まとめ
- クラス内で「自分だけ使うコールバック」ならアロー関数で簡単に安全に
thisを固定できる。 - 「親クラスの処理を呼びたい」「オーバーライドしたい」場合は、プロトタイプメソッド(通常メソッド)を使う。
- どちらも上手く使い分けると、バグを減らしつつ読みやすいコードになります。
