JavaScriptのクラス継承:既存のクラスを元に新しいクラスを作る

クラスの基本を学んだ次は「継承」です。継承を使うことで、すでにあるクラスを元に、新たなクラスを効率よく作成できます。

継承とは

継承は、すでにあるクラスを元に新たなクラスを作成する方法です。

構文: class 子クラス extends 親クラス { }

// 親クラス
class Animal {
  constructor(name) {
    this.name = name;
  }
  
  greet() {
    console.log(`私は${this.name}です`);
  }
}

// 子クラス(Animalを継承)
class Dog extends Animal {
}

const dog = new Dog("ポチ");
dog.greet();  // 私はポチです

extends キーワードを使うことで、親クラスの機能を引き継いだ子クラスを作れます。

子クラスは親クラスのメソッドを使える

子クラスは、親クラスのメソッドをそのまま使えるます。

class Animal {
  constructor(name) {
    this.name = name;
  }
  
  speak() {
    console.log("鳴いています");
  }
  
  info() {
    console.log(`名前: ${this.name}`);
  }
}

class Dog extends Animal {
}

const dog = new Dog("ポチ");
dog.speak();  // 鳴いています(親クラスのメソッドが使える)
dog.info();   // 名前: ポチ

コードを書き直す必要がなく、親クラスのメソッドがそのまま使えます。

メソッド内で戻り値を使う

メソッド内では、関数と同様に戻り値(return)を使うことができます

class Calculator {
  add(a, b) {
    return a + b;
  }
  
  multiply(a, b) {
    return a * b;
  }
}

const calc = new Calculator();
const result = calc.add(3, 5);
console.log(result);  // 8

メソッドから値を返すことで、計算結果を他の処理に使えます。

子クラスのメソッドは親クラスでは使えない

継承は一方向です。子クラスのメソッドは親クラスでは使えません

class Animal {
  speak() {
    console.log("鳴いています");
  }
}

class Dog extends Animal {
  fetch() {
    console.log("ボールを取ってきました");
  }
}

const animal = new Animal();
animal.speak();  // ✅ 使える

const dog = new Dog();
dog.speak();  // ✅ 親クラスのメソッドは使える
dog.fetch();  // ✅ 子クラスのメソッドも使える

// ❌ 親クラスのインスタンスでは子クラスのメソッドは使えない
animal.fetch();  // エラー

オーバーライド:親クラスのメソッドを上書き

オーバーライドとは、子クラスのメソッドが親クラスのメソッドを上書きすることです。

class Animal {
  speak() {
    console.log("動物が鳴いています");
  }
}

class Dog extends Animal {
  speak() {
    console.log("ワンワン!");  // 親クラスのspeakを上書き
  }
}

class Cat extends Animal {
  speak() {
    console.log("ニャーニャー!");  // 親クラスのspeakを上書き
  }
}

const dog = new Dog();
const cat = new Cat();

dog.speak();  // ワンワン!(子クラスのメソッドが実行される)
cat.speak();  // ニャーニャー!(子クラスのメソッドが実行される)

同じ名前のメソッドを子クラスで定義すると、親クラスのメソッドが上書きされます。

コンストラクタのオーバーライド

メソッドと同様に、コンストラクタもオーバーライド可能です。子クラスにプロパティを追加したいときに使用します。

重要:super()が必要

子クラスでコンストラクタをオーバーライドする場合、最初の行に super() の記述が必要です。

構文:

class 子クラス extends 親クラス {
  constructor(引数) {
    super(親クラスへの引数);  // 必ず最初に書く
    // 子クラス独自の処理
  }
}
class Animal {
  constructor(name) {
    this.name = name;
  }
}

class Dog extends Animal {
  constructor(name, breed) {
    super(name);  // 親クラスのコンストラクタを呼び出す
    this.breed = breed;  // 子クラス独自のプロパティ
  }
  
  info() {
    console.log(`名前: ${this.name}`);
    console.log(`犬種: ${this.breed}`);
  }
}

const dog = new Dog("ポチ", "柴犬");
dog.info();
// 名前: ポチ
// 犬種: 柴犬

super()の役割

super() は、親クラスのコンストラクタを呼び出しているものです。

class Animal {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
}

class Dog extends Animal {
  constructor(name, age, breed) {
    super(name, age);  // 親クラスと同様の引数を渡す必要がある
    this.breed = breed;
  }
}

const dog = new Dog("ポチ", 3, "柴犬");
console.log(dog.name);   // ポチ
console.log(dog.age);    // 3
console.log(dog.breed);  // 柴犬

重要: super() には、親クラスのコンストラクタと同じ引数を渡す必要があります

継承を使うメリット

1. コードの再利用

// 継承なしだと、同じコードを書き直す必要がある
class Dog {
  constructor(name) {
    this.name = name;
  }
  speak() {
    console.log("鳴いています");
  }
}

class Cat {
  constructor(name) {  // Dogと全く同じ
    this.name = name;
  }
  speak() {             // Dogと全く同じ
    console.log("鳴いています");
  }
}
// 継承を使うと、共通部分をまとめられる
class Animal {
  constructor(name) {
    this.name = name;
  }
  speak() {
    console.log("鳴いています");
  }
}

class Dog extends Animal {}
class Cat extends Animal {}

2. 保守性の向上

共通の処理を親クラスにまとめることで、変更が必要なときも1箇所修正すれば全体に反映されます。

Pythonとの比較

項目PythonJavaScript
継承class 子(親):class 子 extends 親 {}
親クラス呼び出しsuper().__init__()super()
オーバーライド同名メソッドを定義同名メソッドを定義
# Python
class Animal:
    def __init__(self, name):
        self.name = name

class Dog(Animal):
    def __init__(self, name, breed):
        super().__init__(name)
        self.breed = breed
// JavaScript
class Animal {
  constructor(name) {
    this.name = name;
  }
}

class Dog extends Animal {
  constructor(name, breed) {
    super(name);
    this.breed = breed;
  }
}

基本的な考え方は同じです。

今日の学びのポイント

  • 継承: すでにあるクラスを元に新たなクラスを作成
  • class 子クラス extends 親クラス {} で定義
  • 子クラスは親クラスのメソッドを使える
  • 子クラスのメソッドは親クラスでは使えない
  • オーバーライド: 同名メソッドで上書き
  • コンストラクタのオーバーライドも可能
  • super(): 親クラスのコンストラクタを呼び出す(最初の行に必要)
  • メソッド内で**戻り値(return)**も使える

継承は、大規模なプログラムでコードを整理し、効率よく開発するための重要な技術です。

コメント