Laut Herb Sutter sollte man abstrakte Interfaces (alle rein virtuellen Funktionen) abstrakten Klassen in C ++ vorziehen, um die Implementierung so weit wie möglich zu entkoppeln. Obwohl ich diese Regel persönlich sehr nützlich finde, bin ich kürzlich einem Team mit vielen Java-Programmierern beigetreten, und im Java-Code scheint diese Richtlinie nicht zu existieren. Funktionen und ihre Implementierungen befinden sich sehr häufig in abstrakten Klassen. Habe ich Herb Sutter auch für C ++ falsch verstanden oder gibt es einen allgemeinen Unterschied in der Verwendung von abstrakten Funktionen in C ++ im Vergleich zu Java. Sind abstrakte Klassen mit Implementierungscode in Java sinnvoller als in C ++ und wenn ja, warum?
java
c++
interfaces
abstract-class
Martin
quelle
quelle
Antworten:
OOP hat Zusammensetzung und Substitution.
C ++ verfügt über Mehrfachvererbung, Template-Spezialisierung, Einbettung und Wert- / Verschiebungs- / Zeigersemantik.
Java verfügt über Einzelvererbung und Schnittstellen, Einbettungs- und Referenzsemantik.
Die OOP-Schule verwendet diese Sprachen üblicherweise, indem sie die Vererbung für die Objektsubstitution und die Einbettung für die Komposition einsetzt. Sie brauchen aber auch einen gemeinsamen Vorfahren und einen Weg zur Laufzeitumwandlung (in C ++ heißt das
dynamic_cast
, in Java wird nur eine Schnittstelle von einer anderen abgefragt).Java tut dies alles durch seine eigene
java.lang.Object
verwurzelte Hierarchie. C ++ hat kein vordefiniertes gemeinsames Stammverzeichnis, daher sollten Sie es zumindest definieren, um zu einem "Bild" zu gelangen (dies schränkt jedoch einige C ++ - Möglichkeiten ein ...).Danach kann die Möglichkeit, Polymorphismus zur Kompilierungszeit (nach CRTP denken) und Wertsemantik zu haben, auch andere Alternativen zu der Art und Weise bieten, wie das Konzept des "OOP-Objekts" in ein C ++ - Programm portiert werden kann.
Sie können sich sogar die Häresie vorstellen, die Einbettung und implizite Konvertierung zur Verwaltung der Substitution und die private Vererbung zur Verwaltung der Komposition zu verwenden, wobei das traditionelle Schulparadigma umgekehrt wird. (Natürlich ist dieser Weg 20 Jahre jünger als der andere. Erwarten Sie also keine breite Unterstützung durch die Community.)
Oder Sie können sich eine virtuelle gemeinsame Basis für alle Klassen vorstellen, von der Schnittstelle (keine Implementierung) bis zur endgültigen Klasse (vollständig implementiert), die teilweise implementierte Schnittstellen und gerade Schnittstellencluster durchläuft, wobei "Dominanz" als Versand von Schnittstelle zu Implementierungen über einen "Multi-Stack" verwendet wird -parallelogram "Vererbungsschema.
Der Vergleich von OOP mit Java mit C ++ unter der Annahme, dass es nur einen einzigen OOP-Weg gibt, schränkt die Fähigkeiten beider Sprachen ein.
Das Erzwingen der strikten Einhaltung von Java-Codierungsidiomen durch C ++ bewirkt eine Denaturierung von C ++, da Java gezwungen wird, sich wie eine C ++ - ähnliche Sprache zu verhalten, was Java denaturiert.
Geht es nicht um "Sensibilität", sondern um unterschiedliche "Aggregationsmechanismen", die die beiden Sprachen haben, und um sie auf unterschiedliche Weise zu kombinieren, was eine Redewendung in einer Sprache rentabler macht als in der anderen und umgekehrt.
quelle
Das Prinzip gilt für beide Sprachen, aber Sie führen keinen fairen Vergleich durch. Sie sollten reine abstrakte C ++ - Klassen mit Java-Schnittstellen vergleichen.
Selbst in C ++ können abstrakte Klassen vorhanden sein, in denen einige der Funktionen implementiert sind, die jedoch von einer reinen abstrakten Klasse abgeleitet sind (keine Implementierungen). In Java haben Sie dieselben abstrakten Klassen (mit einigen Implementierungen), die von Interfaces abgeleitet werden können (keine Implementierungen).
quelle
Im Allgemeinen gelten für Java und C ++ dieselben OO-Prinzipien. Ein großer Unterschied ist jedoch, dass C ++ die Mehrfachvererbung unterstützt, während Sie in Java nur von einer Klasse erben können. Dies ist der Hauptgrund, warum Java meiner Meinung nach Schnittstellen hat, um das Fehlen von Mehrfachvererbung zu ergänzen und wahrscheinlich einzuschränken, was Sie damit machen können (da es viel Kritik am Missbrauch von Mehrfachvererbung gibt). Wahrscheinlich gibt es für Java-Programmierer eine stärkere Unterscheidung zwischen abstrakten Klassen und Schnittstellen. Abstrakte Klassen werden verwendet, um das Verhalten zu teilen und zu erben, während Schnittstellen lediglich dazu dienen, zusätzliche Funktionen hinzuzufügen. Denken Sie daran, in Java können Sie nur von einer Klasse erben, aber Sie können viele Schnittstellen haben. In C ++ jedoch reine abstrakte Klassen (dh eine „C ++ Schnittstelle“) sind Wird verwendet, um Verhalten zu teilen und zu erben, das nicht dem Zweck einer Java-Schnittstelle entspricht (obwohl Sie die Funktionen noch implementieren müssen). Daher unterscheidet sich die Verwendung von Java-Schnittstellen.
quelle
Manchmal ist eine Standardimplementierung sinnvoll. Beispiel: Eine generische PrintError-Methode (String-Nachricht), die für alle Unterklassen gilt.
Es kann immer noch überschrieben werden, wenn es wirklich erforderlich ist, aber Sie können dem Client Ärger ersparen, indem Sie ihm erlauben, nur die generische Version aufzurufen.
quelle