1984 Stimmen

Bevorzugen Sie Komposition statt Vererbung?

Warum Komposition der Vererbung vorziehen? Welche Kompromisse gibt es für jeden Ansatz? Wann sollten Sie Vererbung der Komposition vorziehen?

6 Stimmen

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.

2voto

LCJ Punkte 21809

Wie viele Leute gesagt haben, beginne ich mit der Prüfung, ob eine "ist-a"-Beziehung besteht. Wenn dies der Fall ist, prüfe ich normalerweise Folgendes:

Ob die Basisklasse instanziiert werden kann. Das heißt, ob die Basisklasse nicht-abstrakt sein kann. Wenn sie nicht-abstrakt sein kann, bevorzuge ich normalerweise die Komposition

Z.B. 1. Buchhalter ist ein Mitarbeiter. Aber ich werde ノット Vererbung verwenden, da ein Employee-Objekt instanziiert werden kann.

Z.B. 2. Buch ist eine VerkaufenItem. Ein SellingItem kann nicht instanziiert werden - es ist ein abstraktes Konzept. Daher werde ich inheritacne verwenden. Das SellingItem ist ein abstrakte Basisklasse (oder Schnittstelle in C#)

Was halten Sie von diesem Ansatz?

Außerdem unterstütze ich @anon Antwort in Warum überhaupt eine Vererbung?

Der Hauptgrund für die Verwendung von Vererbung ist nicht eine Form der Komposition, sondern die Möglichkeit, polymorphes Verhalten zu erhalten. Wenn Sie keinen Polymorphismus brauchen, sollten Sie wahrscheinlich keine Vererbung verwenden.

@MatthieuM. sagt in https://softwareengineering.stackexchange.com/questions/12439/code-smell-inheritance-abuse/12448#comment303759_12448

Das Problem bei der Vererbung ist, dass sie für zwei unterschiedliche Zwecke verwendet werden kann:

Schnittstelle (für Polymorphismus)

Implementierung (zur Wiederverwendung von Code)

REFERENZ

  1. Welches Klassendesign ist besser?
  2. Vererbung vs. Aggregation

1 Stimmen

Ich bin mir nicht sicher, warum "die Basisklasse ist abstrakt?" in der Diskussion eine Rolle spielt. Die LSP: werden alle Funktionen, die auf Dogs wirken, funktionieren, wenn Poodle-Objekte übergeben werden? Wenn ja, dann kann Poodle durch Dog ersetzt werden und kann somit von Dog erben.

0 Stimmen

@Gishu Danke. Ich werde mich auf jeden Fall mit LSP beschäftigen. Aber vorher können Sie bitte ein Beispiel nennen, in dem Vererbung richtig ist und die Basisklasse nicht abstrakt sein kann. Ich denke, Vererbung ist nur anwendbar, wenn die Basisklasse abstrakt ist. Wenn die Basisklasse separat instanziiert werden muss, ist Vererbung nicht sinnvoll. Das heißt, auch wenn der Buchhalter ein Angestellter ist, sollten Sie keine Vererbung verwenden.

1 Stimmen

Ich habe in letzter Zeit die WCF gelesen. Ein Beispiel im .net-Framework ist SynchronizationContext (Base + kann instanziiert werden), der die Arbeit in eine Warteschlange auf einen ThreadPool-Thread stellt. Ableitungen sind WinFormsSyncContext (Warteschlange auf UI Thread) und DispatcherSyncContext (Warteschlange auf WPF Dispatcher)

1voto

luke1985 Punkte 2245

Diese Vorschrift ist ein völliger Unsinn. Warum?

Der Grund dafür ist, dass man in jedem Fall sagen kann, ob man Komposition oder Vererbung verwenden soll. Dies wird durch die Antwort auf eine Frage bestimmt: "IST etwas A etwas anderes" oder "HAT etwas A etwas anderes".

Man kann nicht "vorziehen", etwas zu etwas anderem zu machen oder etwas anderes zu haben. Es gelten strenge logische Regeln.

Es gibt auch keine "erfundenen Beispiele", da in jeder Situation eine Antwort auf diese Frage gegeben werden kann.

Wenn Sie diese Frage nicht beantworten können, ist etwas anderes falsch. Dazu gehören sich überschneidende Zuständigkeiten von Klassen, die in der Regel das Ergebnis sind von falsche Verwendung von Schnittstellen weniger häufig durch Umschreiben desselben Codes in verschiedenen Klassen.

Um solche Situationen zu vermeiden, empfehle ich auch, gute Namen für Klassen zu verwenden, die ihren Aufgaben voll entsprechen.

3 Stimmen

Ihr Argument ist gut, auch wenn ich denke, dass es etwas besser formuliert werden sollte; außerdem gibt es sind einige Grenzfälle (Sie behaupten, es gäbe gar keine). Der springende Punkt ist, dass die Entscheidung in den meisten Fällen eigentlich sehr einfach ist und nicht als Ermessensentscheidung betrachtet werden sollte. Die eigentliche Frage, die zu beantworten ist, wenn es darum geht, ob ein Foo sein eine Bar oder enthalten wird sein, ob es notwendig sein wird, irgendeinen Code auf dem Rechner zu haben Foo innerhalb einer Bar *unter Beibehaltung seiner Identität als Bar . Wenn nicht, kapseln Sie einfach eine Foo und legen Sie es als Mitglied aus.

0 Stimmen

Nein, es gibt keine Grenzfälle. Jeder Fall kann durch Faktoren gelöst werden, die auf den ersten Blick nicht offensichtlich sind. Die Angelegenheit erfordert eine gründliche Analyse, andernfalls wird eine willkürliche Entscheidung Probleme verursachen, die zu schlechtem Code führen.

0 Stimmen

Und das kann nur semantisch bestimmt werden. Wenn Sie in einer Situation sind, in der Sie irgendeinen Code benötigen, um mit Foo innerhalb eines Bar zu arbeiten, während Sie seine Identität als Bar beibehalten, sollten Sie keine Entscheidung darüber treffen. Sie als Designer der Klassen-API sollten wissen, ob Sie Delegierte verwenden oder dieses Mitglied offenlegen sollen.

0voto

Was wollen Sie sich selbst (oder einem anderen Programmierer) aufzwingen, und wann wollen Sie sich (oder einem anderen Programmierer) mehr Freiheiten lassen. Es wurde argumentiert, dass Vererbung hilfreich ist, wenn man jemanden zwingen will, ein bestimmtes Problem zu behandeln/zu lösen, damit er nicht in die falsche Richtung gehen kann.

Is-a y Has-a ist eine hilfreiche Faustformel.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X