Fireこの広告は、90日以上更新していないブログに表示しています。injectionオブジェクト指向設計において、オブジェクト間の依存をコードの奥深くに埋め込むのは得策ではない。同時に、誰から見て依存関係がはっきりとわかるべきかは、設計者が判断すべきことである。おいて、オブジェクトのユーザーが依存関係を見ていいなら、テンプレートでいいだろう。オブジェクトの設計者だけが依存関係を見るべきなら、インターフェイスを使うべきだろう。あるクラスの実装において、他のクラスの名前を具体的に書くことを避けるためには、例えばインターフェイス(のようなもの)や、テンプレートといった対処法がある。テンプレートは、引数の具体的な型を書くことなしにクラスや関数を宣言・定義することを可能にする。POODRの記事で触れたダックタイピングのひとつでもある。次のようなコードでクラスを宣言したとする。loader);};すると、このクラスは次のようにして使える。コンパイル時に具体的な型名に置き換えられて、実際に使われるコードが生成される。クラステンプレートを使うと、しばしば入れ子のテンプレート表記ができる。次のような定義も書くことができる。data;ここまで来るとさすがに新しくクラスをつくったほうがいいだろうが、このようにテンプレートが入れ子になるとコードは長くなり、あまり見た目はよくない。クラステンプレートを1箇所で使うと、そのクラスを受取るクラスでもテンプレートを使うか、後述のインターフェイスを用いる必要が出てくる。指定して使用されるまで決まらないことによる。まで決まって初めて型として指定できる。何らかの基底クラスを継承した場合は、基底クラスへのアップキャストが機能する。*1ところで、テンプレートに具体的な型を入れて使うコードが見えるのは、たいていクラスのユーザーなので、テンプレートを用いると依存関係を見るのは各クラスのユーザーということになる。これは必ずしもデメリットではなく、ユーザーが自由に依存性を注入できるという意味ではとても自由度の高い設計を実現できるというメリットもある。いうかメリットが非常に大きい。STLはこれによって成り立っている。クラスを、あるインターフェイスクラスの派生クラスとすれば、インターフェイスクラスを介して渡すことができる。{};クラスのユーザーは次のように基底であるインターフェイスを指定する。loader);};すると次のようにアップキャストによって派生クラスを渡すことができる。コンストラクタに渡すことができる。デザパタにあるように、より変更に強い設計を実現するための基本だ。ところで、インターフェイスを用いた依存性注入が行われるのは、クラスの設計者側である。依存関係をクラスのユーザーに見せないことが良い場合もあるだろうし、一方でユーザーが自由に依存性を注入できないことがデメリットになる場合もあるだろう。結局どっちがいいのかインターフェイスとテンプレートのどちらかが絶対に良いということはなく、個々のケースで設計者がどう判断するかによって取るべき方法が自然と決まってくるだけだろう。研究用に自分だけが使うコードならテンプレートを存分に使えるだろうし、フレームワークやツールキットなどの他人に使ってもらうコードならインターフェイスが良いかもしれない。インターフェイスを使うとそのぶんクラスが増え、コード量も増える。一方でテンプレートを使うとヘッダファイルとソースファイルの分離ができなくなる。個人的には見た目がいまいちでも楽なのでテンプレートを使っている。*1:この段落は公開後に追記した。(1)はてなブログをはじめよう!aximovさんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。