Es geht nicht darum, welches das Beste ist, sondern darum, wann was zu verwenden ist.
In den "normalen" Fällen reicht eine einfache Frage aus, um herauszufinden, ob wir Vererbung oder Aggregation benötigen.
- Wenn die neue Klasse ist mehr oder weniger wie die ursprüngliche Klasse. Vererbung verwenden. Die neue Klasse ist jetzt eine Unterklasse der ursprünglichen Klasse.
- Wenn die neue Klasse die ursprüngliche Klasse haben muss . Verwenden Sie die Aggregation. Die neue Klasse hat jetzt die ursprüngliche Klasse als Mitglied.
Es gibt jedoch eine große Grauzone. Wir brauchen also noch einige andere Tricks.
- Wenn wir Vererbung verwendet haben (oder planen, sie zu verwenden), aber nur einen Teil der Schnittstelle verwenden, oder wenn wir gezwungen sind, viele Funktionen zu überschreiben, um die Korrelation logisch zu halten. Dann haben wir einen großen üblen Geruch, der darauf hinweist, dass wir Aggregation verwenden mussten.
- Wenn wir die Aggregation verwendet haben (oder planen, sie zu verwenden), aber feststellen, dass wir fast die gesamte Funktionalität kopieren müssen. Dann haben wir einen Geruch, der in Richtung Vererbung zeigt.
Um es kurz zu machen. Wir sollten die Aggregation verwenden, wenn ein Teil der Schnittstelle nicht verwendet wird oder geändert werden muss, um eine unlogische Situation zu vermeiden. Wir müssen die Vererbung nur verwenden, wenn wir fast die gesamte Funktionalität ohne größere Änderungen benötigen. Verwenden Sie im Zweifelsfall Aggregation.
Eine andere Möglichkeit für den Fall, dass wir eine Klasse haben, die einen Teil der Funktionalität der ursprünglichen Klasse benötigt, besteht darin, die ursprüngliche Klasse in eine Stammklasse und eine Unterklasse aufzuteilen. Und lassen Sie die neue Klasse von der Stammklasse erben. Aber Sie sollten darauf achten, keine unlogische Trennung zu schaffen.
Fügen wir ein Beispiel hinzu. Wir haben eine Klasse 'Hund' mit Methoden: 'Essen', 'Gehen', 'Bellen', 'Spielen'.
class Dog
Eat;
Walk;
Bark;
Play;
end;
Wir brauchen jetzt eine Klasse 'Katze', die 'Essen', 'Gehen', 'Schnurren' und 'Spielen' braucht. Versuchen Sie also zuerst, es von einem Hund zu verlängern.
class Cat is Dog
Purr;
end;
Sieht gut aus, aber warte. Diese Katze kann bellen (Katzenliebhaber werden mich dafür töten). Und eine bellende Katze verstößt gegen die Prinzipien des Universums. Wir müssen also die Bark-Methode überschreiben, damit sie nichts bewirkt.
class Cat is Dog
Purr;
Bark = null;
end;
Ok, das funktioniert, aber es riecht schlecht. Versuchen wir also eine Aggregation:
class Cat
has Dog;
Eat = Dog.Eat;
Walk = Dog.Walk;
Play = Dog.Play;
Purr;
end;
Ok, das ist schön. Diese Katze bellt nicht mehr, nicht einmal still. Aber es hat immer noch einen internen Hund, der raus will. Versuchen wir also Lösung Nummer drei:
class Pet
Eat;
Walk;
Play;
end;
class Dog is Pet
Bark;
end;
class Cat is Pet
Purr;
end;
Das ist viel sauberer. Keine internen Hunde. Und Katzen und Hunde sind auf dem gleichen Niveau. Wir können sogar andere Haustiere vorstellen, um das Modell zu erweitern. Es sei denn, es ist ein Fisch oder etwas, das nicht läuft. In diesem Fall müssen wir erneut umgestalten. Aber das ist etwas für eine andere Zeit.