Die Idee, mehrere Vererbungen in einer Sprache zu unterstützen, hat mir immer gefallen. Meistens wird jedoch absichtlich darauf verzichtet, und der vermeintliche "Ersatz" sind Schnittstellen. Interfaces decken einfach nicht den gleichen Grund ab, den Mehrfachvererbung hat, und diese Einschränkung kann gelegentlich zu mehr Boilerplate-Code führen.
Der einzige Grund, den ich jemals dafür gehört habe, ist das Diamantproblem mit Basisklassen. Das kann ich einfach nicht akzeptieren. Für mich ist es eine Menge, wie: "Nun, es ist möglich , es zu vermasseln, also ist es automatisch eine schlechte Idee." Sie können alles in einer Programmiersprache vermasseln, und ich meine alles. Ich kann das einfach nicht ernst nehmen, zumindest nicht ohne eine gründlichere Erklärung.
Nur sich dieses Problems bewusst zu sein, ist 90% der Schlacht. Ich glaube, ich habe vor einigen Jahren von einem allgemeinen Workaround mit einem "Envelope" -Algorithmus oder ähnlichem gehört (läutet das eine Glocke?).
In Bezug auf das Diamantenproblem ist das einzige potenziell echte Problem, das mir einfällt, wenn Sie versuchen, eine Bibliothek eines Drittanbieters zu verwenden, und nicht sehen können, dass zwei scheinbar nicht miteinander verbundene Klassen in dieser Bibliothek eine gemeinsame Basisklasse haben, aber zusätzlich dazu Die Dokumentation, eine einfache Sprachfunktion, könnte beispielsweise erfordern, dass Sie ausdrücklich Ihre Absicht erklären, einen Diamanten zu erstellen, bevor er tatsächlich einen für Sie kompiliert. Mit einem solchen Merkmal ist jede Kreation eines Diamanten entweder beabsichtigt, rücksichtslos oder weil man sich dieser Fallstricke nicht bewusst ist.
Damit alles gesagt wird ... Gibt es einen wirklichen Grund, warum die meisten Menschen Mehrfachvererbung hassen, oder ist es nur ein Haufen Hysterie, der mehr Schaden als Nutzen verursacht? Gibt es etwas, das ich hier nicht sehe? Danke.
Beispiel
Auto erweitert WheeledVehicle, KIASpectra erweitert Auto und Electronic, KIASpectra enthält Radio. Warum enthält KIASpectra kein elektronisches Produkt?
Denn es ist ein Electronic. Vererbung vs. Komposition sollte immer eine Beziehung sein vs. eine Beziehung.
Denn es ist ein Electronic. Es gibt Drähte, Leiterplatten, Schalter usw., die das Ding auf und ab bewegen.
Denn es ist ein Electronic. Wenn Ihre Batterie im Winter leer ist, haben Sie genauso große Probleme, als wären plötzlich alle Räder verschwunden.
Warum keine Schnittstellen verwenden? Nehmen wir zum Beispiel # 3. Ich will nicht , um darüber zu schreiben und immer wieder, und ich wirklich nicht will , etwas bizarr Proxy Helfer Klasse erstellen , dies zu tun , entweder:
private void runOrDont()
{
if (this.battery)
{
if (this.battery.working && this.switchedOn)
{
this.run();
return;
}
}
this.dontRun();
}
(Wir werden uns nicht damit befassen, ob diese Implementierung gut oder schlecht ist.) Sie können sich vorstellen, wie viele dieser Funktionen in Zusammenhang mit Electronic stehen, die nichts mit WheeledVehicle zu tun haben, und umgekehrt.
Ich war mir nicht sicher, ob ich mich mit diesem Beispiel abfinden sollte oder nicht, da es dort Raum für Interpretationen gibt. Sie könnten auch in Bezug auf die Flugzeugerweiterung von Fahrzeug und FlyingObject und die Vogelerweiterung von Animal und FlyingObject denken, oder in Bezug auf ein viel reineres Beispiel.
Traits
- sie wirken wie Schnittstellen mit optionaler Implementierung, haben jedoch einige Einschränkungen, die das Auftreten von Problemen wie dem Diamantproblem verhindern.
KiaSpectra
ist nicht ein Electronic
; es hat Elektronik, und kann ein ElectronicCar
(was sich verlängern würde Car
...)