TL;DR

継承を使わずにコードを再利用する、オブジェクト指向の設計の原則。共通の親クラスを継承する代わりに、機能を持つオブジェクトをフィールドとして持ち、メソッドの呼び出しをそのオブジェクトに転送(委譲)する。

なぜ必要か

Wikipedia によると、オブジェクトが「何であるか」を継承で広げるより、オブジェクトが「何をできるか」を組み立てるほうがよい。クラスを家系図のように並べず、部品から組み立てるので、設計の柔軟性が上がる。振る舞いを深い継承の階層ではなくインタフェースに分けると、最初の設計も単純になり、要件の変化にも対応しやすい。多くの言語では継承の関係は静的に決まるが、委譲する部品は実行時に差し替えられる。

仕組み

Wikipedia ではゲームを例にしている。見える・見えない、動く・動かない、ぶつかる・ぶつからないという 3 つの振る舞いを、それぞれ差し替えられる実装を持つ抽象クラスとして定義する。ゲームのオブジェクトは、振る舞いごとに委譲先のオブジェクトを 1 つずつ持ち、そのメソッドを呼ぶ。プレイヤーは「見える・動く・ぶつかる」、煙は「見える・動く・ぶつからない」のように、部品の組み合わせで具体的なオブジェクトを作る。この形は、多重継承で起きるダイヤモンド問題も避けられる。

注意点

継承なら親クラスの振る舞いをそのまま使えるが、委譲では転送するメソッドを手で書く必要があることが多い。Go、Rust、Kotlin などは、埋め込みやトレイト、委譲の構文でこの手間を減らしている。Wikipedia は、この原則を文字どおりの掟としてではなく、適した場面で使う指針として受け取るべきだとしている。

関連

出典