effectiveJava項目14のサンプルコードが理解できませんのでどなたかご教授いただけますでしょうか。
継承の代わりにコンポジションを使用するとなっていますが結局Set<E>インターフェースをFowardingSet<E>が
継承しInstrumentedSet<E>がFowardingSet<E>を継承しているという三層構造になっていて継承の代わりにコンポジションを使用するという目的が達成されているように見えません。
サンプルコードの構造が理解できないのでどなたか教えていただけると幸いです。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2018/01/07 09:07
回答2件
0
この件は、簡単に言えば、「責任の負えないクラスを直接継承するな」ということになります。
通常はHashSetのソースコードなんて誰も読んでないですよね。(私は読んでるという方には失礼)
まさかaddAll()のなかでadd()が呼ばれているなんて、、、(まあ予想はつきますが、、)
この内部仕様を知らずに、手軽にカウンターなんてつけちゃうと誤動作するわけです。
そこで、わが所有のインスタンス変数の制御権を取り戻すために、HashSetから切り離すのがこの事例なんです。
よく知らない人クラスに振り回され、原因不明なバグに悩まされるクラスと、完全制御下に置いたクラスとの比較になっています。
投稿2018/01/07 09:07
編集2018/01/07 09:12退会済みユーザー
総合スコア0
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2018/01/07 09:19 編集
2018/01/07 10:00
2018/01/08 07:16 編集
0
ベストアンサー
Effective Javaのソースコードらしきものを見ましたが、確かにコンポジションを使用していますね。
まず、FowardingSetはSetを継承ではなく、実装しています。
ForwardingSetはコンストラクタでSetインターフェースの実装インスタンスをもらってますよね。で、保持してますよね。これはコンポジションです。
コンポジションしないで継承するやり方は、ForwardingSetクラスがコンストラクタにSetインターフェースの実装インスタンスを引数として取らずに、HashSetクラスやInstrumentedHashSetクラスを継承することです。このことにより、ForwardingSetクラスは間接的にSetインターフェースを実装することにもなります。
しかし、そうすると、ForwardingSetクラスは余計なメソッドやフィールドをもらってしまう訳なのです。それはForwardingSetクラスが本来やりたかったことでなく、ForwardingSetクラスのドキュメントも長大化します。
ForwardingSetクラスがやりたいことはSetインターフェースを実装しているクラスについて、Setインターフェース以外のメソッドやフィールドを隠すことです。その上で、InstrumentedSetクラスはカウント機能を追加しています。
なんでそんなことをするかというと、Setインターフェースの実装にはいろいろ種類があって、速度やメモリ使用に関する特性が異なるためです。だから、Setインターフェースの実装が具体的にどれなのかについては、あえて言及していない訳です。
投稿2018/01/07 08:15
総合スコア667
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2018/01/07 08:59
2018/01/07 09:50
2018/01/08 07:30 編集
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。