Ich bin noch Jahre davon entfernt, die Unterscheidung zwischen einer abstrakten Klasse und einer Schnittstelle zu verstehen. Jedes Mal, wenn ich denke, die Grundkonzepte in den Griff zu bekommen, schaue ich auf StackExchange und bin zwei Schritte zurück. Aber ein paar Gedanken zum Thema und zur OP-Frage:
Zuerst:
Es gibt zwei allgemeine Erklärungen für eine Schnittstelle:
Eine Schnittstelle ist eine Liste von Methoden und Eigenschaften, die jede Klasse implementieren kann. Durch die Implementierung einer Schnittstelle garantiert eine Klasse, dass diese Methoden (und ihre Signaturen) und diese Eigenschaften (und ihre Typen) verfügbar sind, wenn eine "Schnittstelle" mit dieser Klasse oder erstellt wird ein Objekt dieser Klasse. Eine Schnittstelle ist ein Vertrag.
Schnittstellen sind abstrakte Klassen, die nichts tun / können. Sie sind nützlich, weil Sie im Gegensatz zu diesen mittleren Elternklassen mehr als eine implementieren können. Ich könnte ein Objekt der Klasse BananaBread sein und von BaseBread erben, aber das heißt nicht, dass ich nicht auch die Schnittstellen IWithNuts und ITastesYummy implementieren kann. Ich könnte sogar die IDoesTheDishes-Schnittstelle implementieren, weil ich nicht nur Brot bin, weißt du?
Es gibt zwei allgemeine Erklärungen für eine abstrakte Klasse:
Eine abstrakte Klasse ist das , was das Ding nicht kann. Es ist wie die Essenz, überhaupt keine echte Sache. Warte, das wird helfen. Ein Boot ist eine abstrakte Klasse, aber eine sexy Playboy-Yacht wäre eine Unterklasse von BaseBoat.
Ich habe ein Buch über abstrakte Klassen gelesen, und vielleicht sollten Sie dieses Buch lesen, weil Sie es wahrscheinlich nicht verstehen und es falsch machen, wenn Sie dieses Buch nicht gelesen haben.
Übrigens, die Buchziter wirken immer beeindruckend, auch wenn ich immer noch verwirrt davongehe.
Zweite:
Auf SO fragte jemand eine einfachere Version dieser Frage, den Klassiker: "Warum Schnittstellen verwenden? Was ist der Unterschied? Was fehle ich?" In einer Antwort wurde ein Luftwaffenpilot als einfaches Beispiel verwendet. Es landete nicht ganz, aber es löste einige großartige Kommentare aus, von denen einer die IFlyable-Schnittstelle mit Methoden wie takeOff, pilotEject usw. erwähnte. aber entscheidend. Eine Schnittstelle macht ein Objekt / eine Klasse intuitiv oder gibt zumindest den Sinn, den es hat. Eine Schnittstelle dient nicht dem Nutzen des Objekts oder der Daten, sondern etwas, das mit diesem Objekt interagieren muss. Der Klassiker Obst-> Apfel-> Fuji oder Form-> Dreieck-> Gleichseitige Beispiele für die Vererbung sind ein hervorragendes Modell für das taxonomische Verständnis eines bestimmten Objekts anhand seiner Nachkommen. Es informiert den Verbraucher und den Verarbeiter über seine allgemeinen Eigenschaften, Verhaltensweisen, ob es sich bei dem Objekt um eine Gruppe von Dingen handelt, wird Ihr System beschädigen, wenn Sie es an der falschen Stelle ablegen, oder es beschreibt sensorische Daten, einen Konnektor zu einem bestimmten Datenspeicher oder Finanzdaten für die Gehaltsabrechnung.
Ein bestimmtes Flugzeugobjekt kann eine Methode für eine Notlandung haben oder nicht, aber ich bin sauer, wenn ich davon ausgehe, dass das Notland wie jedes andere flugfähige Objekt in DumbPlane aufgewacht ist, und erfahre, dass die Entwickler Quickland gewählt haben weil sie dachten, dass es egal sei. Genauso wie ich frustriert wäre, wenn jeder Schraubenhersteller eine eigene Interpretation von Righty Tighty hätte oder wenn mein Fernseher nicht den Lautstärkeregler über dem Lautstärkeregler hätte.
Abstrakte Klassen sind das Modell, das festlegt, was ein untergeordnetes Objekt als diese Klasse qualifizieren muss. Wenn Sie nicht alle Qualitäten einer Ente haben, spielt es keine Rolle, dass Sie das IQuack-Interface implementiert haben, Ihr einziger komischer Pinguin. Schnittstellen sind die Dinge, die Sinn machen, auch wenn Sie sich bei nichts anderem sicher sind. Jeff Goldblum und Starbuck waren beide in der Lage, außerirdische Raumschiffe zu fliegen, da die Benutzeroberfläche zuverlässig ähnlich war.
Dritte:
Ich stimme Ihrem Kollegen zu, denn manchmal müssen Sie bestimmte Methoden von Anfang an durchsetzen. Wenn Sie ein Active Record-ORM erstellen, ist eine Speichermethode erforderlich. Dies hängt nicht von der Unterklasse ab, die instanziiert werden kann. Und wenn die ICRUD-Schnittstelle portabel genug ist, um nicht ausschließlich mit einer abstrakten Klasse gekoppelt zu werden, kann sie von anderen Klassen implementiert werden, um sie für jeden, der bereits mit einer der abgeleiteten Klassen dieser abstrakten Klasse vertraut ist, zuverlässig und intuitiv zu machen.
Auf der anderen Seite gab es bereits ein gutes Beispiel dafür, wann nicht eine Schnittstelle an die abstrakte Klasse gebunden werden sollte, da nicht alle Listentypen eine Warteschlangenschnittstelle implementieren (oder sollten). Sie sagten, dass dieses Szenario die Hälfte der Zeit passiert, was bedeutet, dass Sie und Ihr Kollege beide die Hälfte der Zeit falsch liegen. Daher ist es das Beste, zu argumentieren, zu debattieren, zu überlegen und die Kopplung zu akzeptieren, wenn sie sich als richtig herausstellt . Werden Sie jedoch kein Entwickler, der einer Philosophie folgt, auch wenn diese für den jeweiligen Job nicht die beste ist.