Composition over Inheritance:継承より合成を優先する

入門 | 9分 で読める | 2026.06.18

公式ドキュメント

Composition over Inheritance は、「継承より合成を優先する」という設計原則です。

オブジェクト指向を学ぶと継承が便利に見えますが、使いすぎると変更に弱くなります。

一言でいうと

継承で親子関係を深くするより、小さな部品を組み合わせるほうが変更しやすい場面があります。

継承は「AはBの一種である」という関係を表します。合成は「AはBを持っている」という関係を表します。

継承の例

class EmailNotifier {
 send(message: string) {
 console.log(`email: ${message}`);
 }
}

class WelcomeEmailNotifier extends EmailNotifier {
 sendWelcome(userName: string) {
 this.send(`Welcome ${userName}`);
 }
}

単純な例では問題ありません。しかし、継承階層が深くなると、親クラスの変更が子クラスへ広く影響します。

合成の例

class WelcomeMessageService {
 constructor(private readonly notifier: Notifier) {}

 sendWelcome(userName: string) {
 this.notifier.send(`Welcome ${userName}`);
 }
}

通知方法を外から渡しています。メール通知、Slack通知、テスト用通知を差し替えやすくなります。

継承がつらくなるサイン

サイン問題
親クラスが大きい子クラスが不要な機能まで持つ
子クラスが増えすぎる変更影響が読みにくい
overrideが多い親の設計と合わなくなっている
継承階層が深い実際の処理を追うのが大変
テストしにくい親クラスの状態に依存する

継承は便利ですが、親の都合に子が縛られます。

合成が向いている場面

  • 処理の一部を差し替えたい
  • テスト用の実装を渡したい
  • 複数の振る舞いを組み合わせたい
  • 親子関係より役割の組み合わせで表せる
  • 将来の変更点が部品ごとに違う

たとえば、通知、保存、ログ、認証、支払いなどの外部処理は、合成やDIと相性がよいです。

継承を使ってよい場面

継承が悪いわけではありません。

「本当にAはBの一種」と言える場合、フレームワークの拡張ポイントとして決まっている場合、共通の契約を表す場合には使えます。

ただし、コード再利用だけを目的に継承するのは注意です。

まとめ

Composition over Inheritance は、継承より合成を優先して考える設計原則です。

親子関係で縛るより、小さな役割を組み合わせるほうが、差し替えやテストがしやすくなります。

参考リソース

関連記事

← 一覧に戻る
PR
PR
PR
PR