どちらが最善であるかではなく、何をいつ使用するかが問題になります。
「通常の」ケースでは、単純な質問で、継承または集約が必要かどうかを確認できます。
- 新しいクラスが元のクラスとほぼ同じ場合。継承を使用します。新しいクラスは、元のクラスのサブクラスになりました。
- 新しいクラスは、必要がある場合は持って元のクラスを。集計を使用します。新しいクラスには、元のクラスがメンバーとして含まれています。
ただし、大きな灰色の領域があります。したがって、他のいくつかのトリックが必要です。
- 継承を使用した(または使用を計画している)が、インターフェースの一部のみを使用している場合、または相関を論理的に保つために多くの機能をオーバーライドする必要がある場合。次に、集計を使用する必要があったことを示す大きな嫌なにおいがあります。
- 集約を使用した(または使用する予定がある)が、ほぼすべての機能をコピーする必要があることがわかった場合。すると、相続の方向を指す匂いがします。
短くする。インターフェースの一部が使用されていない場合、または非論理的な状況を回避するために変更する必要がある場合は、集約を使用する必要があります。大きな変更なしにほぼすべての機能が必要な場合にのみ、継承を使用する必要があります。疑問がある場合は、集計を使用してください。
元のクラスの機能の一部を必要とするクラスがある場合のもう1つの可能性は、元のクラスをルートクラスとサブクラスに分割することです。そして、新しいクラスにルートクラスを継承させます。しかし、非論理的な分離を作成するのではなく、これに注意する必要があります。
例を追加してみましょう。「犬」というメソッドがあり、「食べる」、「歩く」、「吠える」、「遊ぶ」があります。
class Dog
Eat;
Walk;
Bark;
Play;
end;
ここで、「食べる」、「歩く」、「パー」、および「再生」を必要とするクラス「猫」が必要です。だから最初に犬からそれを拡張してみてください。
class Cat is Dog
Purr;
end;
よし、よし、待って。この猫は吠えることができます(猫愛好家はそのために私を殺します)。そして吠える猫は宇宙の原則に違反しています。したがって、何も実行しないようにBarkメソッドをオーバーライドする必要があります。
class Cat is Dog
Purr;
Bark = null;
end;
わかりました、これは機能しますが、悪臭がします。だから集計を試してみましょう:
class Cat
has Dog;
Eat = Dog.Eat;
Walk = Dog.Walk;
Play = Dog.Play;
Purr;
end;
わかりました。この猫はもう吠えず、沈黙もしません。しかし、それでも外に出たがっている犬がいます。ソリューション番号3を試してみましょう:
class Pet
Eat;
Walk;
Play;
end;
class Dog is Pet
Bark;
end;
class Cat is Pet
Purr;
end;
これはずっときれいです。内部の犬はありません。猫と犬は同じレベルです。他のペットを紹介してモデルを拡張することもできます。魚、または歩かないものでない限り。その場合、再びリファクタリングする必要があります。しかし、それはまた別のことです。