Wann können Sie die Komposition verwenden?
Sie können immer die Komposition verwenden. In einigen Fällen ist auch die Vererbung möglich und kann zu einer leistungsfähigeren und/oder intuitiveren API führen, aber die Komposition ist immer eine Option.
Wann können Sie die Vererbung nutzen?
Es wird oft gesagt, dass, wenn "a bar is a foo", dann die Klasse Bar
kann die Klasse Foo
. Leider ist dieser Test allein nicht zuverlässig, verwenden Sie stattdessen den folgenden Test:
- ein bar ist ein foo, UND
- Bars können alles, was Foos können.
Der erste Test stellt sicher, dass alle Getter de Foo
sinnvoll sein in Bar
(= gemeinsame Eigenschaften), während der zweite Test sicherstellt, dass alle Einsteller de Foo
sinnvoll sein in Bar
(= gemeinsame Funktionalität).
Beispiel: Hund/Tier
Ein Hund ist ein Tier UND Hunde können alles tun, was Tiere tun können (z. B. atmen, sich bewegen usw.). Daher ist die Klasse Dog
puede die Klasse erben Animal
.
Gegenbeispiel: Kreis/Ellipse
Ein Kreis ist eine Ellipse, ABER Kreise können nicht alles, was Ellipsen können. Zum Beispiel können Kreise nicht gestreckt werden, während Ellipsen dies können. Deshalb ist die Klasse Circle
no puede die Klasse erben Ellipse
.
Dies wird als die Kreis-Ellipse-Problem was nicht wirklich ein Problem ist, sondern eher ein Hinweis darauf, dass "a bar is a foo" an sich kein zuverlässiger Test ist. Insbesondere zeigt dieses Beispiel, dass abgeleitete Klassen erweitern. die Funktionalität von Basisklassen, niemals einschränken es. Andernfalls könnte die Basisklasse nicht polymorph verwendet werden. Das Hinzufügen des Tests "bars can do everything that foos can do" stellt sicher, dass die polymorphe Verwendung möglich ist, und ist äquivalent zu Liskov-Substitutionsprinzip :
Funktionen, die Zeiger oder Verweise auf Basisklassen verwenden, müssen in der Lage sein, Objekte abgeleiteter Klassen zu verwenden, ohne dies zu wissen
Wann sollten Sie die Vererbung nutzen?
Auch wenn Sie puede Vererbung zu verwenden, bedeutet nicht, dass Sie devrait : Die Verwendung von Komposition ist immer eine Option. Die Vererbung ist ein leistungsfähiges Werkzeug, das die implizite Wiederverwendung von Code und die dynamische Verteilung ermöglicht, aber sie bringt auch einige Nachteile mit sich, weshalb die Komposition oft bevorzugt wird. Die Kompromisse zwischen Vererbung und Komposition sind nicht offensichtlich und werden meiner Meinung nach am besten erklärt in lcn's Antwort .
Als Faustregel neige ich dazu, die Vererbung der Komposition vorzuziehen, wenn die polymorphe Verwendung voraussichtlich sehr häufig vorkommt. In diesem Fall kann die Leistung der dynamischen Abfertigung zu einer viel besser lesbaren und eleganten API führen. Zum Beispiel, eine polymorphe Klasse zu haben Widget
in GUI-Frameworks, oder eine polymorphe Klasse Node
in XML-Bibliotheken ermöglicht eine API, die viel lesbarer und intuitiver zu verwenden ist als eine Lösung, die nur auf Komposition basiert.
6 Stimmen
Siehe auch welches Klassendesign besser ist
6 Stimmen
In einem Satz Vererbung ist öffentlich, wenn Sie eine öffentliche Methode haben und Sie ändern es ändert die veröffentlichte api. wenn Sie Zusammensetzung haben und das Objekt komponiert hat sich geändert, müssen Sie nicht Ihre veröffentlichte api ändern.