2024年3月23日

クラスの継承

クラスの継承は、あるクラスが別のクラスを拡張するための方法です。

つまり、既存の機能の上に、新たな機能を作ることができます。

“extends” キーワード

クラス Animal があるとします:

class Animal {
  constructor(name) {
    this.speed = 0;
    this.name = name;
  }
  run(speed) {
    this.speed += speed;
    alert(`${this.name} runs with speed ${this.speed}.`);
  }
  stop() {
    this.speed = 0;
    alert(`${this.name} stopped.`);
  }
}

let animal = new Animal("My animal");

これは、animal オブジェクトと Animal クラスを、グラフィカルに表現したものです。:

…そしてもう1つの class Rabbit を作成します。

うさぎ(rabbit)は動物(animal)なので、Rabbit クラスは Animal がベースとなり、animal メソッドへアクセスできます。これで、“一般的な” 動物が実行できることをうさぎも実行できます。

別のクラスを拡張する構文は class Child extends Parent です。

Animal を継承した class Rabbit を作成しましょう。:

class Rabbit extends Animal {
  hide() {
    alert(`${this.name} hides!`);
  }
}

let rabbit = new Rabbit("White Rabbit");

rabbit.run(5); // White Rabbit runs with speed 5.
rabbit.hide(); // White Rabbit hides!

Rabbit クラスのオブジェクトは、rabbit.hide() のように Rabbit のメソッドと、rabbit.run() のように Animal メソッド両方が利用できます。

内部では、extends キーワードは、以前からあるプロトタイプの仕組みを使用して動作しています。Rabbit.prototype.[[Prototype]]Animal.prototype にセットします。そのため、Rabbit.prototype でメソッドが見つからない場合には、JavaScript は Animal.prototype から取得します。

例えば、rabbit.run メソッドを見つけるために、エンジンは次のようにチェックします(図の下から上):

  1. rabbit オブジェクト(run はありません)。
  2. そのプロトタイプ、つまり Rabbit.prototype(hide はありますが、runはありません)。
  3. そのプロトタイプ、つまり (extends しているため) Animal.prototype, (最終的に run メソッドを持ちます)。