woshidan's blog

そんなことよりコードにダイブ。

転送と委譲の定義について

自分で書いてて、あれ、どっちがどっちだっけ、と少し混乱したので手持ちの本をぱらぱらと見て整理してました。

Effective Javaに書いてある転送と委譲の定義みたいなもの

以下は、Effective Javaに書いてある説明をざっとまとめたものになります。

転送

転送とは、既存クラスのカプセル化を壊さないようにしつつ既存クラスのメソッドを利用するために、インスタンスを参照するprivateのフィールドを持つラッパークラスを用意して、ラッパークラスのメソッドに対して、既存クラスのメソッドの結果を返すようにすること。

既存クラスを継承して拡張していく場合、拡張したメソッドは既存クラスの実装の詳細を気にしながら実装していく必要があります。こういった場合は、既存クラスのカプセル化が壊されている、といいます。

そういう場合、継承の代わりに、既存クラスのインスタンスを参照するprivateのフィールドを持つラッパークラスを用意します。

既存のクラスが新たなクラスの構成要素になるので、こうした設計は コンポジション(Composition) と呼ばれます。

そして、新たなクラスの各インスタンスメソッドで、それぞれのメソッドに対する既存クラスのメソッドを呼び出してその結果を返すようにします。これを 転送(forwarding) といい、新たなクラスのメソッドは 転送メソッド(forwarging method) と呼びます。

委譲

時折、コンポジションと転送の組み合わせがおおざっぱに 委譲(delegation) と呼ばれることがあります。技術的には、ラッパーオブジェクトがラップしているオブジェクトへ自分自身を渡さない限り、委譲ではありません。

他の本の定義とか

たとえば、「Java言語で学ぶデザインパターン入門」では、委譲について

Javaでの委譲は、あるメソッドの実際の処理を他のインスタンスのメソッドに任せてしまうことをいいます

と書いてあり、実装を見ると、コンポジションと転送の組み合わせのことを言っています。

また、「Effective Ruby」では、メソッド呼び出しをインスタンス変数に転送することを委譲といっているみたいです。

まとめ

厳しい人からしたら技術的には若干微妙な可能性もありますが、だいたい、委譲と言われたら、コンポジションと転送の組み合わせのことを言われている感じがします。

委譲って具体的にどのメソッドを何のインスタンスに転送しているんだ、みたいな詳細のことを言う時に転送、という言葉を使われているようです。

コミュニティによって若干意味が異なってくる可能性のある言葉なので、注意しながら使ったほうがよさそうです。

EFFECTIVE JAVA 第2版 (The Java Series)

EFFECTIVE JAVA 第2版 (The Java Series)

増補改訂版Java言語で学ぶデザインパターン入門

増補改訂版Java言語で学ぶデザインパターン入門

Effective Ruby

Effective Ruby