判断ガイド: 継承かコンポジションか¶
判断フロー¶
Q1. 目的は「抽象(インターフェース)の実装」か?
→ はい ──> 継承でよい(純粋仮想の実装は健全な継承)
Q2. 目的は「実装(コード)の再利用」か?
→ はい ──> コンポジション(部品として持つ)を既定とする。Q3で例外確認
Q3. 例外チェック: 次の3条件が全部成り立つか?
(a) is-aが契約レベルで成立([LSP](../02_solid/lsp.md): 置換しても呼び出し側の期待を破らない)
(b) 階層は浅い(1〜2段)まま安定しそう
(c) 基底の変更が派生を壊す結合を受け入れられる(同一チーム・同時変更が可能)
→ 全部Yes ──> 継承も可(Template Method型の骨格共有など)
→ 1つでもNo ──> コンポジション
Q4. 「特徴の組み合わせ」を表現したいか?(飛ぶ×撃つ×分裂)
→ はい ──> 迷わずコンポジション(継承ツリーは組み合わせで爆発する)
根拠: 継承・委譲・コンポジション、LSP、Strategy
判断材料¶
- 継承の危険シグナル: 空実装のoverride/基底のprotectedメンバを派生が直接いじる/「〜だけど〜しない」型(飛べない鳥)/派生の追加のたび基底に条件分岐が増える
- コンポジションの危険シグナル: 部品が2つで固定なのに差し替え基盤を整備/部品間の通信コードが本体より太い(部品の切り方=責務の切り方が誤り)
例外¶
- フレームワーク規約: MonoBehaviour、AActor、Screen基底などエンジン・基盤の指定する継承は従う(規約への準拠であり、この判断の対象外)
- バリエーション2つで固定: enum+ifの方が誠実なこともある(継承もコンポジションも過剰)
トレードオフ¶
| 継承 | コンポジション | |
|---|---|---|
| 得 | 記述が短い、型で能力が分かる、フックの規約提供 | 組み合わせ自由、実行時差し替え、弱い結合 |
| 失 | 最強の結合(基底変更の波及)、組み合わせ爆発、実行時変更不可 | 部品接続コード、追跡の手間、設計力を要求 |
実践のコツ¶
- 迷ったらコンポジション(戻しやすいのはこちら。継承を剥がすのは大工事)
- 「継承で共有したい実装」は、大抵部品クラス1つ+両者がそれを持つで書き直せる——書き直してみて不自然なら継承の兆候
理解度チェック¶
- 「インターフェースの実装」の継承が例外的に安全なのはなぜですか。
- Q3の3条件のうち、実務で最も破られやすいのはどれだと思いますか。
- 継承もコンポジションも過剰な状況とは?
前: インターフェースを作るべきか | カテゴリ目次 | 次: 抽象化すべきか・パターンを使うべきか