JavaScript | classの継承(extends)

JavaScript JavaScript
スポンサーリンク

では「JavaScriptでのオブジェクト指向設計のベストプラクティス」として、継承よりコンポジションを優先する考え方を整理してみましょう。これは実務でもよく言われる「Composition over Inheritance(継承より合成を)」という原則です。


なぜ「継承よりコンポジション」なのか

  • 継承の問題点
    • 親子関係が強く結びつきすぎる(親を変えると子も壊れる)
    • 階層が深くなると理解しづらい
    • 「is-a」関係でないのに無理に継承すると不自然な設計になる
  • コンポジションの利点
    • 部品を組み合わせるだけなので柔軟
    • 再利用性が高い(同じ部品をいろんなクラスに持たせられる)
    • 依存関係が浅く、変更に強い

例題:ゲームキャラクターに「飛ぶ能力」を追加する

❌ 継承でやると…

class Character {
  constructor(name){ this.name = name; }
}

class FlyingCharacter extends Character {
  fly(){
    console.log(`${this.name} が空を飛んだ!`);
  }
}

let hero = new FlyingCharacter("勇者");
hero.fly(); // → 勇者 が空を飛んだ!
JavaScript

👉 「飛べるキャラ」と「飛べないキャラ」を分けるためにクラスを増やすと、
「飛べる魔法使い」「飛べるモンスター」などが必要になり、クラス爆発が起きる。


✅ コンポジションでやると…

// 共通のキャラクター
class Character {
  constructor(name){ this.name = name; }
}

// 「飛ぶ能力」を部品として定義
class FlyAbility {
  fly(name){
    console.log(`${name} が空を飛んだ!`);
  }
}

// キャラクターに「飛ぶ能力」を持たせる
let hero = new Character("勇者");
hero.flyAbility = new FlyAbility();

hero.flyAbility.fly(hero.name); 
// → 勇者 が空を飛んだ!
JavaScript

👉 「飛ぶ能力」を部品として切り出すことで、
勇者でも魔法使いでもモンスターでも、必要なときだけ組み合わせられる。


✅ まとめ

  • 継承は「is-a」関係(犬は動物の一種)で使う
  • コンポジションは「has-a」や「can-do」関係(キャラは武器を持つ/飛ぶことができる)で使う
  • 実務では「まずコンポジションを検討し、必要なときだけ継承」を選ぶのがベストプラクティス

💡 初心者へのアドバイス:

  • 「これは本当にis-a関係か?」と考えてから継承を選ぶ
  • 「能力・機能を追加したい」ならコンポジションで組み合わせる方が柔軟
タイトルとURLをコピーしました