it-swarm-eu.dev

Woher kommt dieses Konzept der "Bevorzugung der Komposition gegenüber der Vererbung"?

In den letzten Monaten scheint das Mantra "Komposition gegenüber Vererbung bevorzugen" aus dem Nichts entstanden und zu einer Art Mem innerhalb der Programmiergemeinschaft geworden zu sein. Und jedes Mal, wenn ich es sehe, bin ich ein bisschen verwirrt. Es ist, als hätte jemand gesagt: "Bevorzugen Sie Bohrer gegenüber Hämmern." Nach meiner Erfahrung sind Komposition und Vererbung zwei verschiedene Werkzeuge mit unterschiedlichen Anwendungsfällen, und es macht keinen Sinn, sie so zu behandeln, als ob sie austauschbar wären und eines dem anderen von Natur aus überlegen wäre.

Außerdem sehe ich nie eine wirkliche Erklärung für warum Vererbung ist schlecht und Komposition ist gut, was mich nur misstrauischer macht. Soll es nur im Glauben akzeptiert werden? Liskov-Substitution und Polymorphismus haben bekannte, eindeutige Vorteile, und IMO umfasst den gesamten Punkt der objektorientierten Programmierung, und niemand erklärt jemals, warum sie zugunsten der Komposition verworfen werden sollten.

Weiß jemand, woher dieses Konzept kommt und was die Gründe dafür sind?

145
Mason Wheeler

Obwohl ich glaube, ich habe schon lange vor GoF Diskussionen über Komposition und Vererbung gehört, kann ich nicht auf eine bestimmte Quelle eingehen. Könnte sowieso Booch gewesen sein.

<rant>

Ah, aber wie viele Mantras ist auch dieses nach typischen Grundsätzen entartet:

  1. es wird mit einer detaillierten Erklärung und Argumentation von einer angesehenen Quelle eingeleitet, die den Slogan als Erinnerung an die ursprüngliche komplexe Diskussion prägt.
  2. es wird von einigen Kennern für eine Weile mit einem wissenden Teil des Clubs geteilt, im Allgemeinen, wenn sie n00b-Fehler kommentieren
  3. bald wird es von Tausenden und Abertausenden sinnlos wiederholt, die die Erklärung nie lesen, aber es lieben, sie als Ausrede zu benutzen, nicht zu denken , und als billig und einfach Weg, sich anderen überlegen zu fühlen
  4. schließlich kann keine vernünftige Entlarvung die "Meme" -flut eindämmen - und das Paradigma degeneriert in Religion und Dogma.

Das Mem, das ursprünglich dazu gedacht war, n00bs zur Aufklärung zu führen, wird jetzt als Club verwendet, um sie bewusstlos zu schlagen.

Zusammensetzung und Vererbung sind sehr unterschiedliche Dinge und sollten nicht miteinander verwechselt werden. Zwar kann die Komposition verwendet werden, um die Vererbung mit viel zusätzlicher Arbeit zu simulieren, dies macht die Vererbung jedoch nicht zu einem Bürger zweiter Klasse und tut dies auch nicht es macht die Komposition zum Lieblingssohn. Die Tatsache, dass viele n00bs versuchen, die Vererbung als Verknüpfung zu verwenden, macht den Mechanismus nicht ungültig, und fast alle n00bs lernen aus dem Fehler und verbessern sich dadurch.

Bitte DENKE über deine Entwürfe nach und hör auf, Slogans auszusprechen.

</ rant>

139
Steven A. Lowe

Erfahrung.

Wie Sie sagen, sie sind Werkzeuge für verschiedene Jobs, aber der Satz entstand, weil die Leute ihn nicht auf diese Weise benutzten.

Vererbung ist in erster Linie ein polymorphes Werkzeug, aber einige Leute versuchen, sehr zu ihrer späteren Gefahr, es als Mittel zur Wiederverwendung/Weitergabe von Code zu verwenden. Das Grundprinzip lautet: "Wenn ich erbe, bekomme ich alle Methoden kostenlos", ignoriert jedoch die Tatsache, dass diese beiden Klassen möglicherweise keine polymorphe Beziehung haben.

Warum also Komposition gegenüber Vererbung bevorzugen - einfach, weil die Beziehung zwischen Klassen meistens keine polymorphe ist. Es dient lediglich dazu, die Menschen daran zu erinnern, dass sie nicht durch Erben auf einen Knie-Ruck reagieren.

75
Stephen Bailey

Es ist keine neue Idee, ich glaube, sie wurde tatsächlich in das 1994 veröffentlichte GoF-Designmusterbuch aufgenommen.

Das Hauptproblem bei der Vererbung ist, dass es sich um eine White-Box handelt. Per Definition müssen Sie die Implementierungsdetails der Klasse kennen, von der Sie erben. Bei der Komposition hingegen interessiert Sie nur die öffentliche Oberfläche der Klasse, die Sie komponieren.

Aus dem GoF-Buch:

Durch die Vererbung wird eine Unterklasse Details der Implementierung des übergeordneten Elements ausgesetzt. Es wird häufig gesagt, dass die Vererbung die Kapselung unterbricht.

Der Wikipedia-Artikel im GoF-Buch enthält eine anständige Einführung.

43
Dean Harding

Um einen Teil Ihrer Frage zu beantworten, glaube ich, dass dieses Konzept erstmals im Buch GOF Design Patterns: Elements of Reusable Object-Oriented Software veröffentlicht wurde, das 1994 erstmals veröffentlicht wurde. Der Satz erscheint oben auf der Seite 20, in der Einleitung:

Bevorzugen Sie die Objektzusammensetzung gegenüber der Vererbung

Sie beginnen diese Aussage mit einem kurzen Vergleich der Vererbung mit der Zusammensetzung. Sie sagen nicht "niemals Vererbung verwenden".

27
vjones

"Zusammensetzung über Vererbung" ist eine kurze (und anscheinend irreführende) Art zu sagen: "Wenn Sie der Meinung sind, dass die Daten (oder das Verhalten) einer Klasse in eine andere Klasse aufgenommen werden sollten, sollten Sie immer die Verwendung von Komposition in Betracht ziehen, bevor Sie die Vererbung blind anwenden.".

Warum ist das wahr? Da durch die Vererbung eine enge Kopplung zur Kompilierungszeit zwischen den beiden Klassen entsteht. Im Gegensatz dazu ist die Zusammensetzung eine lose Kopplung, die unter anderem eine klare Trennung von Bedenken, die Möglichkeit des Wechsels von Abhängigkeiten zur Laufzeit und eine einfachere, isoliertere Abhängigkeitstestbarkeit ermöglicht.

Das bedeutet nur, dass die Vererbung mit Vorsicht behandelt werden sollte, da sie mit Kosten verbunden ist und nicht, dass sie nicht nützlich ist. Tatsächlich ist "Komposition über Vererbung" häufig "Komposition + Vererbung über Vererbung", da Sie häufig möchten, dass Ihre zusammengesetzte Abhängigkeit eher eine abstrakte Oberklasse als die konkrete Unterklasse selbst ist. Sie können zur Laufzeit zwischen verschiedenen konkreten Implementierungen Ihrer Abhängigkeit wechseln.

Aus diesem Grund (unter anderem) wird die Vererbung wahrscheinlich häufiger in Form von Schnittstellenimplementierungen oder abstrakten Klassen verwendet als die Vanilla-Vererbung.

Ein (metaphorisches) Beispiel könnte sein:

"Ich habe eine Snake-Klasse und möchte als Teil dieser Klasse angeben, was passiert, wenn die Snake beißt. Ich wäre versucht, die Snake eine BiterAnimal-Klasse mit der Bite () -Methode erben zu lassen und diese Methode zu überschreiben, um den giftigen Biss widerzuspiegeln Aber Komposition über Vererbung warnt mich, dass ich versuchen sollte, stattdessen Komposition zu verwenden ... In meinem Fall könnte dies dazu führen, dass die Schlange ein Bite-Mitglied hat. Die Bite-Klasse könnte abstrakt (oder eine Schnittstelle) mit mehreren Unterklassen sein. Dies würde es ermöglichen me Schöne Dinge wie VenomousBite- und DryBite-Unterklassen und die Möglichkeit, den Biss auf derselben Snake-Instanz zu ändern, wenn die Schlange älter wird. Wenn ich alle Effekte eines Bites in einer eigenen Klasse handhabe, kann ich ihn in dieser Frost-Klasse wiederverwenden , weil Frost beißt, aber kein BiterAnimal ist, und so weiter ... "

24
guillaume31

Einige mögliche Argumente für die Komposition:

Die Komposition ist etwas sprach-/rahmenunabhängiger
Die Vererbung und das, was sie erzwingt/erfordert/ermöglicht, unterscheiden sich zwischen den Sprachen hinsichtlich des Zugriffs auf die Unterklasse/Superklasse und der möglichen Auswirkungen auf die Leistung für virtuelle Methoden usw. Die Komposition ist recht einfach und erfordert nur sehr wenig Sprache Unterstützung und damit Implementierungen über verschiedene Plattformen/Frameworks hinweg können Kompositionsmuster einfacher gemeinsam nutzen.

Komposition ist eine sehr einfache und taktile Art, Objekte zu bauen
Vererbung ist relativ leicht zu verstehen, aber im wirklichen Leben immer noch nicht so leicht nachzuweisen. Viele Objekte im wirklichen Leben können in Teile zerlegt und zusammengesetzt werden. Angenommen, ein Fahrrad kann mit zwei Rädern, einem Rahmen, einem Sitz, einer Kette usw. gebaut werden. Während man in einer Erbschaftsmetapher sagen könnte, dass ein Fahrrad ein Einrad verlängert, etwas machbar, aber immer noch viel weiter vom tatsächlichen Bild entfernt als die Komposition (offensichtlich ist dies kein sehr gutes Erbschaftsbeispiel, aber der Punkt bleibt der gleiche). Sogar die Wortvererbung (zumindest von den meisten US-Englischsprechern, die ich erwarten würde) ruft automatisch eine Bedeutung in der Richtung "Etwas, das von einem verstorbenen Verwandten weitergegeben wurde" auf, die in gewissem Zusammenhang mit ihrer Bedeutung in der Software steht, aber immer noch nur lose passt.

Die Zusammensetzung ist fast immer flexibler
Mit Komposition können Sie jederzeit Ihr eigenes Verhalten definieren oder einfach diesen Teil Ihrer komponierten Teile verfügbar machen. Auf diese Weise sehen Sie sich keiner der Einschränkungen gegenüber, die durch eine Vererbungshierarchie (virtuell oder nicht virtuell usw.) auferlegt werden können.

Dies könnte daran liegen, dass Komposition natürlich eine einfachere Metapher ist, die weniger theoretische Einschränkungen aufweist als Vererbung. Darüber hinaus können diese besonderen Gründe während der Entwurfszeit offensichtlicher sein oder möglicherweise auffallen, wenn einige der Schwachstellen der Vererbung behandelt werden.

Haftungsausschluss:
Offensichtlich ist es nicht diese klare Einbahnstraße. Jedes Design verdient die Bewertung mehrerer Muster/Werkzeuge. Vererbung ist weit verbreitet, hat viele Vorteile und ist oft eleganter als Komposition. Dies sind nur einige mögliche Gründe, die man bei der Bevorzugung der Komposition verwenden könnte.

22
TJB

Vielleicht haben Sie gerade bemerkt, dass Leute dies in den letzten Monaten gesagt haben, aber es ist guten Programmierern schon viel länger bekannt. Ich habe es sicherlich seit etwa einem Jahrzehnt gesagt, wo es angebracht ist.

Der Punkt des Konzepts ist, dass die Vererbung einen großen konzeptionellen Aufwand verursacht. Wenn Sie die Vererbung verwenden, enthält jeder einzelne Methodenaufruf einen impliziten Versand. Wenn Sie tiefe Vererbungsbäume oder Mehrfachversand oder (noch schlimmer) beides haben, kann es zu einer königlichen PITA werden, herauszufinden, wohin die bestimmte Methode in einem bestimmten Anruf versendet. Dies macht das korrekte Denken über den Code komplexer und das Debuggen schwieriger.

Lassen Sie mich ein einfaches Beispiel zur Veranschaulichung geben. Angenommen, tief in einem Vererbungsbaum hat jemand eine Methode foo genannt. Dann kommt jemand anderes und fügt foo oben im Baum hinzu, macht aber etwas anderes. (Dieser Fall tritt häufiger bei Mehrfachvererbung auf.) Jetzt hat diese Person, die in der Stammklasse arbeitet, die obskure untergeordnete Klasse gebrochen und merkt es wahrscheinlich nicht. Sie könnten eine 100% ige Abdeckung mit Komponententests haben und diesen Bruch nicht bemerken, da die Person an der Spitze nicht daran denken würde, die untergeordnete Klasse zu testen, und die Tests für die untergeordnete Klasse nicht daran denken, die oben erstellten neuen Methoden zu testen . (Zugegeben, es gibt Möglichkeiten, Komponententests zu schreiben, die dies erfassen, aber es gibt auch Fälle, in denen Sie Tests nicht einfach auf diese Weise schreiben können.)

Wenn Sie dagegen Komposition verwenden, ist bei jedem Anruf in der Regel klarer, an wen Sie den Anruf senden. (OK, wenn Sie die Umkehrung der Steuerung verwenden, z. B. mit Abhängigkeitsinjektion, kann es auch problematisch sein, herauszufinden, wohin der Anruf geht. In der Regel ist es jedoch einfacher, dies herauszufinden.) Dies erleichtert das Überlegen. Als Bonus führt die Komposition dazu, dass die Methoden voneinander getrennt sind. Das obige Beispiel sollte dort nicht vorkommen, da die untergeordnete Klasse zu einer obskuren Komponente wechseln würde und es nie eine Frage gibt, ob der Aufruf von foo für die obskure Komponente oder das Hauptobjekt bestimmt war.

Jetzt haben Sie absolut Recht, dass Vererbung und Zusammensetzung zwei sehr unterschiedliche Werkzeuge sind, die zwei verschiedenen Arten von Dingen dienen. Sicher, Vererbung ist mit konzeptionellem Aufwand verbunden, aber wenn es das richtige Werkzeug für den Job ist, ist der konzeptionelle Aufwand geringer als der Versuch, ihn nicht zu verwenden und von Hand zu tun, was er für Sie tut. Niemand, der weiß, was er tut, würde sagen, dass Sie niemals Vererbung verwenden sollten. Aber seien Sie sicher, dass es das Richtige ist.

Leider lernen viele Entwickler objektorientierte Software kennen, lernen Vererbung kennen und verwenden dann so oft wie möglich ihre neue Axt. Das bedeutet, dass sie versuchen, Vererbung zu verwenden, wenn die Komposition das richtige Werkzeug war. Hoffentlich lernen sie mit der Zeit besser, aber häufig geschieht dies erst nach ein paar entfernten Gliedmaßen usw. Wenn man ihnen im Voraus sagt, dass es eine schlechte Idee ist, kann dies den Lernprozess beschleunigen und Verletzungen reduzieren.

11
btilly

Es ist eine Reaktion auf die Beobachtung, dass OO Anfänger dazu neigen, Vererbung zu verwenden, wenn sie es nicht brauchen. Vererbung ist sicherlich keine schlechte Sache, kann aber überbeansprucht werden. Wenn eine Klasse nur Funktionalität benötigt von einem anderen, dann wird die Komposition wahrscheinlich funktionieren. Unter anderen Umständen wird die Vererbung funktionieren und die Komposition nicht.

Das Erben von einer Klasse impliziert viele Dinge. Dies impliziert, dass eine abgeleitete Basis eine Art Basis ist (siehe Liskov-Substitutionsprinzip für die wichtigsten Details), da es sinnvoll ist, eine abgeleitete Basis zu verwenden, wenn Sie eine Basis verwenden. Es gibt dem Abgeleiteten Zugriff auf die geschützten Mitglieder und Mitgliedsfunktionen von Base. Es ist eine enge Beziehung, was bedeutet, dass es eine hohe Kopplung aufweist und Änderungen an der einen eher Änderungen an der anderen erfordern.

Kopplung ist eine schlechte Sache. Es macht es schwieriger, Programme zu verstehen und zu ändern. Wenn andere Dinge gleich sind, sollten Sie immer die Option mit weniger Kopplung auswählen.

Wenn daher entweder die Komposition oder die Vererbung die Aufgabe effektiv erledigt, wählen Sie die Komposition, da die Kopplung geringer ist. Wenn die Komposition die Aufgabe nicht effektiv erledigt und die Vererbung dies nicht tut, wählen Sie die Vererbung, da dies erforderlich ist.

8
David Thornley

Hier sind meine zwei Cent (über alle bereits angesprochenen hervorragenden Punkte hinaus):

IMHO, es kommt auf die Tatsache an, dass die meisten Programmierer nicht wirklich Vererbung bekommen und es am Ende übertreiben, teilweise aufgrund der Art und Weise, wie dieses Konzept gelehrt wird. Dieses Konzept dient dazu, sie davon abzubringen, es zu übertreiben, anstatt sich darauf zu konzentrieren, ihnen beizubringen, wie man es richtig macht.

Jeder, der Zeit mit Unterrichten oder Mentoring verbracht hat, weiß, dass dies häufig vorkommt, insbesondere bei neuen Entwicklern, die Erfahrung mit anderen Paradigmen haben:

Diese Entwickler glauben zunächst, dass Vererbung dieses beängstigende Konzept ist. So erstellen sie am Ende Typen mit Schnittstellenüberschneidungen (z. B. dasselbe spezifizierte Verhalten ohne gemeinsame Untertypisierung) und mit Globalen zum Implementieren gemeinsamer Funktionen.

Dann (oft als Ergebnis übereifrigen Unterrichts) lernen sie die Vorteile der Vererbung kennen, aber es wird oft als die Gesamtlösung für die Wiederverwendung gelehrt. Sie haben die Auffassung, dass jedes gemeinsame Verhalten durch Vererbung geteilt werden muss. Dies liegt daran, dass der Fokus häufig eher auf der Vererbung der Implementierung als auf der Subtypisierung liegt.

In 80% der Fälle ist das gut genug. Bei den anderen 20% beginnt das Problem. Um ein Umschreiben zu vermeiden und sicherzustellen, dass sie die gemeinsame Nutzung der Implementierung genutzt haben, beginnen sie, ihre Hierarchie eher um die beabsichtigte Implementierung als um die zugrunde liegenden Abstraktionen herum zu entwerfen. Der "Stapel erbt von einer doppelt verknüpften Liste" ist ein gutes Beispiel dafür.

Die meisten Lehrer bestehen an dieser Stelle nicht darauf, das Konzept der Schnittstellen einzuführen, da es sich entweder um ein anderes Konzept handelt oder weil Sie sie (in C++) mit abstrakten Klassen und Mehrfachvererbung fälschen müssen, die zu diesem Zeitpunkt nicht gelehrt werden. In Java unterscheiden viele Lehrer nicht zwischen "keine Mehrfachvererbung" oder "Mehrfachvererbung ist böse" und der Bedeutung von Schnittstellen.

All dies wird durch die Tatsache verstärkt, dass wir so viel von der Schönheit gelernt haben, keinen überflüssigen Code mit Implementierungsvererbung schreiben zu müssen, dass Tonnen von einfachem Delegierungscode unnatürlich aussehen. Die Komposition sieht also chaotisch aus, weshalb wir diese Daumenregeln benötigen, um neue Programmierer dazu zu bringen, sie trotzdem zu verwenden (was sie auch übertreiben).

8
Uri

In einem der Kommentare erwähnte Mason, dass wir eines Tages über Vererbung als schädlich angesehen sprechen würden.

Hoffentlich.

Das Problem mit der Vererbung ist gleichzeitig einfach und tödlich. Es respektiert nicht die Idee, dass ein Konzept eine Funktionalität haben sollte.

In den meisten OO-Sprachen haben Sie beim Erben von einer Basisklasse:

  • erben von seiner Schnittstelle
  • von seiner Implementierung erben (sowohl Daten als auch Methoden)

Und hier wird das Problem.

Dies ist nicht der einzige Ansatz, obwohl 00-Sprachen meistens daran festhalten. Glücklicherweise gibt es in diesen Schnittstellen/abstrakte Klassen.

Auch die mangelnde Leichtigkeit, etwas anderes zu tun, trägt dazu bei, dass es weitgehend genutzt wird: Ehrlich gesagt, würden Sie, selbst wenn Sie dies wissen, von einer Schnittstelle erben und die Basisklasse nach Komposition einbetten und die meisten Methodenaufrufe delegieren? Es wäre jedoch erheblich besser, wenn Sie plötzlich gewarnt würden, wenn plötzlich eine neue Methode in der Benutzeroberfläche auftaucht und bewusst entscheiden müsste, wie sie implementiert werden soll.

Als Kontrapunkt erlaubt Haskell die Verwendung des Liskov-Prinzips nur, wenn es von reinen Schnittstellen (so genannten Konzepten) "abgeleitet" wird (1). Sie können nicht von einer vorhandenen Klasse ableiten. Nur durch Komposition können Sie deren Daten einbetten.

(1) Konzepte können einen sinnvollen Standard für eine Implementierung darstellen. Da sie jedoch keine Daten enthalten, kann dieser Standard nur anhand der anderen vom Konzept vorgeschlagenen Methoden oder anhand von Konstanten definiert werden.

8
Matthieu M.

Ich denke, diese Art von Rat ist wie zu sagen "lieber fahren als fliegen". Das heißt, Flugzeuge haben alle möglichen Vorteile gegenüber Autos, aber das bringt eine gewisse Komplexität mit sich. Wenn also viele Menschen versuchen, vom Stadtzentrum in die Vororte zu fliegen, müssen sie wirklich, wirklich hören, dass sie nicht fliegen müssen, und tatsächlich schafft es das Fliegen einfach auf lange Sicht komplizierter, auch wenn es kurzfristig cool/effizient/einfach erscheint. Wenn Sie tun fliegen müssen, sollte dies im Allgemeinen offensichtlich sein.

Ebenso kann Vererbung Dinge bewirken, die Komposition nicht kann, aber Sie sollten dies verwenden, wenn Sie es benötigen, und nicht, wenn Sie es nicht tun. Wenn Sie also nie versucht sind anzunehmen, dass Sie Vererbung benötigen, wenn Sie dies nicht tun, brauchen Sie nicht den Rat "Komposition bevorzugen". Aber viele Leute do und do brauchen diesen Rat.

Es sollte implizit sein, dass es offensichtlich ist, wenn Sie wirklich Vererbung benötigen, und Sie sollten es dann verwenden.

Auch Steven Lowes Antwort. Wirklich, wirklich das.

7
Jack V.

Die einfache Antwort lautet: Vererbung hat eine größere Kopplung als Zusammensetzung. Wählen Sie bei zwei Optionen mit ansonsten gleichwertigen Eigenschaften die weniger gekoppelte.

7
Jeffrey Faust

Vererbung ist nicht von Natur aus schlecht und Komposition ist nicht von Natur aus gut. Sie sind lediglich Werkzeuge, mit denen ein OO Programmierer) Software entwerfen kann.

Wenn Sie sich eine Klasse ansehen, tut sie dann mehr, als sie unbedingt sollte ( SRP )? Dupliziert es unnötig Funktionen ( DRY ) oder ist es übermäßig an den Eigenschaften oder Methoden anderer Klassen interessiert ( Feature Envy ) ?. Wenn die Klasse alle diese Konzepte (und möglicherweise mehr) verletzt, versucht sie, eine Gottklasse zu sein. Dies sind eine Reihe von Problemen, die beim Entwerfen von Software auftreten können, von denen keines notwendigerweise ein Vererbungsproblem darstellt, die jedoch schnell zu großen Kopfschmerzen und spröden Abhängigkeiten führen können, wenn auch Polymorphismus angewendet wurde.

Die Ursache des Problems liegt wahrscheinlich weniger in einem mangelnden Verständnis der Vererbung als vielmehr in einer schlechten Wahl in Bezug auf das Design oder darin, dass "Code-Gerüche" in Bezug auf Klassen, die sich nicht an die Prinzip der Einzelverantwortung. Polymorphismus und Liskov-Substitution müssen nicht zugunsten der Zusammensetzung verworfen werden. Der Polymorphismus selbst kann angewendet werden, ohne auf Vererbung angewiesen zu sein. Dies sind alles recht komplementäre Konzepte. Wenn nachdenklich angewendet. Der Trick besteht darin, Ihren Code einfach und sauber zu halten und nicht übermäßig besorgt über die Anzahl der Klassen zu sein, die Sie erstellen müssen, um ein robustes Systemdesign zu erstellen.

In Bezug auf die Bevorzugung der Komposition gegenüber der Vererbung ist dies nur ein weiterer Fall der sorgfältigen Anwendung der Gestaltungselemente, die im Hinblick auf das zu lösende Problem am sinnvollsten sind. Wenn Sie nicht benötigen, um Verhalten zu erben, sollten Sie dies wahrscheinlich nicht tun, da die Komposition später dazu beiträgt, Inkompatibilitäten und größere Umgestaltungsbemühungen zu vermeiden. Wenn Sie andererseits feststellen, dass Sie viel Code wiederholen, sodass sich die gesamte Duplizierung auf eine Gruppe ähnlicher Klassen konzentriert, kann das Erstellen eines gemeinsamen Vorfahren dazu beitragen, die Anzahl identischer Aufrufe und Klassen zu verringern Möglicherweise müssen Sie zwischen den einzelnen Klassen wiederholen. Sie bevorzugen also die Komposition, gehen jedoch nicht davon aus, dass die Vererbung niemals anwendbar ist.

2
S.Robins