Auf Wunsch von exizt erweitere ich meinen Kommentar zu einer längeren Antwort.
Der größte Fehler, den die Leute machen, ist zu glauben, dass Schnittstellen einfach leere abstrakte Klassen sind. Eine Schnittstelle ist eine Möglichkeit für einen Programmierer zu sagen: "Es ist mir egal, was Sie mir geben, solange es dieser Konvention folgt."
Die .NET-Bibliothek dient als wunderbares Beispiel. Wenn Sie beispielsweise eine Funktion schreiben, die eine akzeptiert IEnumerable<T>
, sagen Sie: "Es ist mir egal, wie Sie Ihre Daten speichern. Ich möchte nur wissen, dass ich eine foreach
Schleife verwenden kann.
Dies führt zu einem sehr flexiblen Code. Um integriert zu werden, müssen Sie plötzlich nur noch die Regeln der vorhandenen Schnittstellen einhalten. Wenn die Implementierung der Schnittstelle schwierig oder verwirrend ist, ist dies möglicherweise ein Hinweis darauf, dass Sie versuchen, einen quadratischen Stift in ein rundes Loch zu schieben.
Aber dann stellt sich die Frage: "Was ist mit der Wiederverwendung von Code? Meine CS-Professoren sagten mir, dass die Vererbung die Lösung für alle Probleme bei der Wiederverwendung von Code ist und dass die Vererbung es Ihnen ermöglicht, einmal zu schreiben und überall zu verwenden, und Menangitis bei der Rettung von Waisenkindern heilen würde von den aufsteigenden Meeren und es würde keine Tränen mehr geben und weiter und weiter usw. usw. usw. "
Die Verwendung der Vererbung, nur weil Sie den Klang der Wörter "Wiederverwendung von Code" mögen, ist eine ziemlich schlechte Idee. Der Code-Styling-Leitfaden von Google macht diesen Punkt ziemlich präzise:
Zusammensetzung ist oft angemessener als Vererbung. ... [B] Da der Code, der eine Unterklasse implementiert, zwischen der Basis und der Unterklasse verteilt ist, kann es schwieriger sein, eine Implementierung zu verstehen. Die Unterklasse kann keine Funktionen überschreiben, die nicht virtuell sind, sodass die Unterklasse die Implementierung nicht ändern kann.
Um zu veranschaulichen, warum Vererbung nicht immer die Antwort ist, verwende ich eine Klasse namens MySpecialFileWriter †. Eine Person, die blindlings glaubt, dass Vererbung die Lösung für alle Probleme ist, würde argumentieren, dass Sie versuchen sollten, von zu erben FileStream
, damit Sie FileStream
den Code nicht duplizieren . Kluge Leute erkennen, dass das dumm ist. Sie sollten nur ein FileStream
Objekt in Ihrer Klasse haben (entweder als lokale oder als Mitgliedsvariable) und dessen Funktionalität verwenden.
Das FileStream
Beispiel mag erfunden erscheinen, ist es aber nicht. Wenn Sie zwei Klassen haben, die beide dieselbe Schnittstelle auf genau dieselbe Weise implementieren, sollten Sie eine dritte Klasse haben, die jede duplizierte Operation kapselt. Ihr Ziel sollte es sein, Klassen zu schreiben, die in sich geschlossene wiederverwendbare Blöcke sind, die wie Legos zusammengestellt werden können.
Dies bedeutet nicht, dass Vererbung um jeden Preis vermieden werden sollte. Es gibt viele Punkte zu beachten, und die meisten werden durch die Untersuchung der Frage "Zusammensetzung vs. Vererbung" abgedeckt. Unser eigener Stapelüberlauf hat einige gute Antworten zu diesem Thema.
Letztendlich fehlt den Gefühlen Ihres Mitarbeiters die Tiefe oder das Verständnis, die erforderlich sind, um eine fundierte Entscheidung zu treffen. Erforschen Sie das Thema und finden Sie es selbst heraus.
† Bei der Veranschaulichung der Vererbung verwendet jeder Tiere. Das ist nutzlos. In 11 Jahren Entwicklungszeit habe ich noch nie eine Klasse mit dem Namen geschrieben Cat
, daher werde ich sie nicht als Beispiel verwenden.
alligator
Die Implementierung voneat
unterscheidet sich natürlich darin, dass siecat
unddog
als Parameter akzeptiert .