深い継承の限界
CoddyのJavaScriptジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 48/56。
継承は便利ですが、非常に深い継承階層(親 → 子 → 孫 → ひ孫)を作ると、問題が生じることがあります。階層が深くなるほど、コードの理解、保守、変更が難しくなります。
継承が深く連なるとどうなるか見てみましょう:
// 基底クラス
class Vehicle {
constructor(type) {
this.type = type;
this.isRunning = false;
}
start() {
this.isRunning = true;
console.log(`${this.type} started`);
}
}
// 継承の第1階層
class Car extends Vehicle {
constructor(make, model) {
super("Car");
this.make = make;
this.model = model;
this.wheels = 4;
}
honk() {
console.log("Beep beep!");
}
}
// 継承の第2階層
class SportsCar extends Car {
constructor(make, model, topSpeed) {
super(make, model);
this.topSpeed = topSpeed;
}
race() {
this.start();
console.log(`Racing at ${this.topSpeed} mph!`);
}
}この例では、SportsCarは継承関係で2階層下にあります。これにより、いくつかの問題が発生する可能性があります。
- Vehicleの変更によって、予期せずSportsCarが壊れる可能性があります
- 継承の階層が深くなるにつれて、メソッドやプロパティがどこから来ているのかを追跡するのが難しくなります
- 柔軟性が十分でない可能性のある「is-a」関係を強いられます
チャレンジ
ロボットを機能させるために、Robot.jsファイルを完成させましょう。現時点ではロボットは組み立てられていますが、何もできません。
Robot.jsで行うこと:
- 作成する Robotのコンストラクター内に、speakerコンポーネントとmoverコンポーネントを作成します
- 使用する メソッド内でコンポーネントを使います:
greet()内:this.speaker.speak("Hello!");を呼び出しますwalkForward()内:this.mover.move("forward");を呼び出します
なぜこうするのか: これはコンポジションです。ロボットは、小さなコンポーネントを組み合わせて作られています。ロボットはこれらの能力を継承するのではなく、speaker(話すため)とmover(動くため)を持っているのです。
自分で試してみよう
import { Robot } from './Robot.js';
const myRobot = new Robot('Robo');
myRobot.greet(); // 出力されるはず: Saying: "Hello!"
myRobot.walkForward(); // 出力されるはず: Moving forwardこのレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: JavaScriptオンラインコンパイラ