50

この質問にはすでに答えがあります。

相続よりも有利な構成

とても人気のあるフレーズです。私はいくつかの記事を読み、最後に各記事は言う

クラス間に純粋なIS-A関係がある場合は、継承を使用してください。

からの例この記事

ここから林檎そしてフルーツ明確なIS-A関係、すなわちApple IS-A Fruitがありますが、それでも継承して実装した場合の落とし穴を示すためにApple HAS-A Fruit(作曲)として示しています。

私はここで声明の意味は何ですかということで多少混乱しました

クラス間に純粋なIS-A関係がある場合は、継承を使用してください。

継承よりもコンポジションを使うということは、常にやってみるコンポジションを適用するたとえ純粋なIS-A関係があり、継承を残す構図が意味をなさない場合のみ


  • なぜJavaラベルなのか - TT_

7 답변


68

メソッドをオーバーライドして別の多態性の振る舞いを定義するのではなく、継承を使用してスーパークラスのコードを再利用する場合、多くの場合、継承の代わりに合成を使用する必要があります。

java.util.Propertiesclassは継承の悪用の良い例です。のではなく使うそのプロパティを格納するためのハッシュテーブル伸びるそのメソッドを再利用し、それらのうちのいくつかを委譲を使って再実装することを避けるためのハッシュテーブル。


  • 車、動物、果物が関係しないのは本当の例なので、私は支持しました。しかし、それがどうやってjava.util.Properties伸びるHashTableその結果、デザインに悪影響を及ぼしています。私はLiskov Substitution Principleについて考えましたが、問題ではないと思います。理論的には、パフォーマンス(メモリ)の観点から格納(ハッシュ)メカニズムを変更できると便利かもしれませんが、継承では不可能であり、合成でも可能です。 - Fuhrmanator
  • 非理論的な質問:すべてのサブクラスが持つべき完全な意味を持ち、どの基本クラスもオーバーライドしないメソッドを含む、基本クラス(抽象的であれば)を書くことはお勧めできません。'方法は?ではありませんProperties伸びるHashtable継承の悪用の良い例を挙げようProperties全体を気にしないでくださいHashtable固有のロジックで、そのサブセットのみが必要なので拡張しないでください。Hashtableなぜならです一つではない、それだけ用途1 ? - SantiBailors

5

これは、オブジェクト指向設計で最も議論されている点の1つです。この記事で示唆されているように、コンポジションは継承よりも常に優先されます。それはあなたが継承を使用してはいけないという意味ではありません。あなたはそれがより理にかなっているところ(それは議論の余地があるかもしれません)にあるべきです。

コンポジションを使用することには多くの利点があります。

  • あなたはあなたの実装を完全に制御するでしょう。つまり、公開する予定のメソッドだけを公開できます。
  • スーパークラスの変更は、自分のクラス内でのみ変更することで保護できます。自分のクラスを使用するクライアントクラスは、変更する必要はありません。
  • スーパークラスをロードするタイミングを制御できます(遅延ロード)。


  • 私が抱えている問題は、もっと合成する方向に動いても構わないということですが、多くのメソッドを持つクラスでは、派生クラスごとにその定型句を繰り返すのは面倒です。もちろん、ほとんどのクラスにはいくつかのメソッドしかありませんが、場合によっては(GUIウィンドウの基本クラスなど)、それらのメソッドをたくさん手に入れるのを手助けすることはできません。 - LegendLength

3

この記事には、そのようなフレーズはありません。

use inheritance when there is pure IS-A relationship between classes

さらに、グーグルはあなたの投稿以外にそれを見つけられませんでした。

代わりに、記事は読みます:

Make sure inheritance models the is-a relationship. My main guiding philosophy is that inheritance should be used only when a subclass is-a superclass. In the example above, an Apple likely is-a Fruit, so I would be inclined to use inheritance.

つまり、IS_A関係がある場合は、コンポジションではなく継承を最初に使用してください。そしての好みはありませんusing composition over inheritance - それぞれが自分の役割に適しています。


  • each is good for its own role.+1。これは「私たちの動機」にかかっていると思います。私達は私達のクラス間の関係を確立しています。 「オンリー」の場合コードの再利用Favor composition over inheritance有効であり、その動機が「実際の関係」をモデル化することである場合。実際にはクラス間に存在するため、継承と合成の両方が独自の役割を果たします。 「にもかかわらず」純粋なIS-A関係がある場合は、継承を選択できます。継承は強い結合のように合成よりも多くの問題を抱えているという事実が、そうでなければ合成を選びます。私は正しいですか? - a Learner
  • コードの再利用は強力な動機です。それだけで継承を選択するのに十分かもしれません。多くの場合、強い結合は問題よりも有利であると考えられます。そして多くの言語(java)では、継承は合成よりも簡単です。経験だけがあなたに与えられたケースのための正しいアプローチが何であるかの感覚を与えることができる、厳密な規則はありません。 - Alexei Kaigorodov

3

また、それを追加したいと思いますデコレータパターン継承に対する合成を使用し、オブジェクトに責任を動的に追加できる例です。 Decoratorパターンの例は、Effective Javaの項目「継承に優先する構成」で説明されています。 Java APIから例を取ります。 BufferedReaderは(FileReader、PipedReader、FilterReaderなどを拡張するのではなく)Readerを装飾するため、あらゆる種類のReaderを装飾することができます。実行時にこれらのリーダーにバッファリング機能が追加されます。これがDecoratorパターンです。

ここでは、サブクラス化による拡張は実用的ではありません。


3

私は良いガイドラインがあると思います:

IS-A関係がある場合は、継承を使用してください。それ以外の場合は   組成。

その理由は、オブジェクト指向設計におけるもう1つの概念 - 多態性 - に関連しています。多態性は、最初のクラスが2番目のクラスのサブクラスであるという条件で、あるオブジェクトを別のオブジェクトの代わりに使用できる多くのOOP言語の機能です。

例証するために、あなたが動物のタイプを取り込む機能を持っているかどうか想像してください。継承を使うときは、関数は1つだけです。

void feed( Animal a );

多型性は私たちが入れた動物のどんなサブクラスでも受け入れられることを私たちに保証します。そうでなければ、それぞれの型に対して一つの関数を書くことを強いられるでしょう。私はこれの利点がその欠点(例:カプセル化の減少)を上回ると思います。

IS-A関係がなければ、多態性はそれほど効果的ではないと思います。したがって、合成を使用し、クラス間のカプセル化/分離を強化することをお勧めします。


  • If there is no IS-A relationship, I think polymorphism won't be very effective. It would thus be better to use composition and have enhanced encapsulation/isolation between classes.+1 - a Learner

2

関係が永続的な場合は継承を使用してください。自由な振る舞いをするためだけにextensionを使わないでください。これは彼らがIS-Aの例で言及しているものです。拡張クラスが本当に親の拡張である場合にのみ拡張します。それが切られて乾いていない時があるでしょう、しかし一般に。あなたが「正しい」クラスから拡張する必要があるならば、構成も将来の柔軟性を提供します。

これは古くからの素晴らしい拡張記事です。

http://www.javaworld.com/javaworld/jw-08-2003/jw-0801-toolbox.html


0

私はノーと言うでしょう。フルーツ/アップルのシナリオでは、継承を使用するのが理にかなっています。記事の執筆者は、「上の例では、Appleは実はFruitである可能性が高いので、継承を使用する傾向がある」とも述べています。

サブクラスが明らかにスーパークラスであれば、継承は問題ありません。しかし実際には、コンポジションを使用して解決した状況がもっとたくさんあります。


  • "サブクラスが明らかにスーパークラスである場合? - Simon Nickerson
  • @SimonNickerson" If<what-your-subclass-models>明らかにIS-A<what-your-superclass-models>" - Joffrey

リンクされた質問


関連する質問

最近の質問