どちらが優れているかではなく、いつ何を使うかが重要です。
「通常の」ケースでは、単純な質問で、継承または集約が必要かどうかを判断できます。
- 新しいクラスは、多かれ少なかれ元のクラスと同じです。継承を使用します。新しいクラスは、元のクラスのサブクラスになりました。
- 新しいクラスに元のクラスが必要な場合。集計を使用します。新しいクラスには、元のクラスがメンバーとして含まれるようになりました。
ただし、大きなグレーゾーンがあります。そのため、他にもいくつかのトリックが必要です。
- 継承を使用した (または使用する予定である) が、インターフェイスの一部しか使用していない場合、または相互関係を論理的に保つために多くの機能をオーバーライドする必要がある場合。次に、集約を使用しなければならなかったことを示す大きな不快な臭いがします。
- 集計を使用したことがある (または使用する予定である) が、ほぼすべての機能をコピーする必要があることがわかった場合。次に、継承の方向を示す匂いがあります。
短くするために。インターフェイスの一部が使用されていない場合、または非論理的な状況を避けるために変更する必要がある場合は、集約を使用する必要があります。大きな変更を加えずにほぼすべての機能が必要な場合にのみ、継承を使用する必要があります。疑わしい場合は、集約を使用してください。
元のクラスの機能の一部を必要とするクラスがある場合の別の可能性は、元のクラスをルートクラスとサブクラスに分割することです。そして、新しいクラスがルート クラスから継承されるようにします。ただし、非論理的な分離を作成しないように、これに注意する必要があります。
例を追加しましょう。「食べる」、「歩く」、「吠える」、「遊ぶ」というメソッドを持つクラス「犬」があります。
class Dog
Eat;
Walk;
Bark;
Play;
end;
ここで、「食べる」、「歩く」、「喉を鳴らす」、「遊ぶ」を必要とするクラス「Cat」が必要です。したがって、最初に Dog から拡張してみてください。
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;
これははるかにきれいです。室内犬なし。そして猫と犬は同じレベルです。モデルを拡張するために他のペットを導入することもできます。魚か、歩かないものでない限り。その場合、再度リファクタリングする必要があります。しかし、それはまた別の機会に。