Gibt es einen Unterschied zwischen Schnittstellen und abstrakten Klassen, die nur abstrakte Methoden haben?

9

Nehmen wir an, wir haben eine abstrakte Klasse und lassen diese Klasse nur abstrakte Methoden haben. Unterscheidet sich diese abstrakte Klasse von einer Schnittstelle, die nur dieselben Methoden hat?

Ich möchte wissen, ob es sowohl philosophisch, objektiv als auch in der zugrunde liegenden Programmiersprachenimplementierung Unterschiede zwischen einer abstrakten Klasse mit nur abstrakten Mitgliedern und einer gleichwertigen Schnittstelle gibt.

yfklon
quelle
welche Sprache?
Kevin Cline
Soweit ich das beurteilen kann, wird Ihre Frage zweimal doppelt beantwortet : hier und hier . Und diese beiden Antworten sind sprachunabhängig, nichts Spezielles für C # dort
Mücke
3
@blank Ich war mit dem auf Ihre Frage angewendeten Status "Duplizieren" nicht einverstanden, daher habe ich ihn erneut geöffnet. Weiter habe ich Ihre Frage bearbeitet, um weiter zu klären, was Sie meiner Meinung nach fragen.
maple_shaft

Antworten:

22

Technisch gesehen sind die Unterschiede nicht wirklich signifikant, aber konzeptionell sind sie völlig verschiedene Dinge, und das führt zu den technischen Unterschieden, die andere erwähnt haben.

Eine abstrakte Superklasse ist genau das, wonach es sich anhört. Es ist ein allgemeiner Typ, der von vielen anderen Typen geteilt wird, wie Katzen und Hunde sind Tiere.

Eine Schnittstelle ist auch genau das, wonach sie sich anhört. Sie ist eine Schnittstelle, über die andere Klassen mit dem Objekt kommunizieren können. Wenn Sie einen Cat Walk durchführen möchten, sind Sie in Ordnung, da Cat eine CanWalk-Schnittstelle implementiert. Das gleiche gilt für eine Eidechse, obwohl sie sehr unterschiedlich laufen. Eine Schlange hingegen implementiert CanWalk nicht, sodass Sie nicht sagen können, dass sie laufen soll. In der Zwischenzeit könnten Lizard und Snake (oder möglicherweise explizitere Unterklassen - ich bin kein Experte) beide ihre Haut abwerfen und so CanShed implementieren, während eine Katze dies nicht konnte.

Aber sie sind alle noch Tiere und haben einige gemeinsame Eigenschaften, zum Beispiel ob sie leben oder tot sind.

Aus diesem Grund müssen alle Methoden auf einer Schnittstelle als öffentlich (oder explizit in C #) implementiert werden. Ursache, was bringt eine Schnittstelle, die vor der Klasse verborgen ist, die mit dem Objekt verbunden ist? Dies ist auch der Grund, warum Sie mehrere Schnittstellen zu einem Objekt haben können, auch wenn eine Sprache keine Mehrfachvererbung unterstützt.

Um auf Ihre Frage zurückzukommen: Wenn Sie sie so betrachten, gibt es sehr selten einen Grund, eine völlig abstrakte Oberklasse zu haben.

pdr
quelle
4
+1, obwohl Katzen viel nerviger vergießen als Schlangen oder Eidechsen.
Matthew Flynn
Technisch: Abstrakte Methoden können geschützt werden. Schnittstellenmethoden können nicht.
Jacques Koorts
19

In den meisten OOP-Sprachen kann eine implementierende Klasse nur von einer abstrakten Klasse abgeleitet sein, jedoch mehrere Schnittstellen implementieren.

herzmeister
quelle
3
die meisten? welche zählst du Die meisten mir bekannten OOP-Sprachen haben keine Schnittstellen oder abstrakten Klassen. C ++ hat nur abstrakte Klassen.
Kevin Cline
10
@kevincline: wahrscheinlich C #, Java und VB.NET.
tdammers
1
@kevincline, ich denke, es fehlt nur ein "beides haben". IIRC, in Ada war die Motivation für die Schnittstelle, dass die Designer keine allgemeine Mehrfachvererbungsfunktion wollten, aber der Sonderfall der Schnittstelle wurde als zu wichtig erachtet, um nicht bereitgestellt zu werden.
AProgrammer
@tdammers: LOL. Das war ein Witz, oder?
Kevin Cline
3

In einer Sprache wie C ++, die Mehrfachvererbung zulässt und keine Schnittstellen hat, können abstrakte Klassen, in denen alle Methoden abstrakt sind, als Schnittstellen dienen. Ich habe nicht so viel mit C ++ gearbeitet, aber ich denke, dass Mehrfachvererbung Probleme verursachen kann, wenn es Methoden mit demselben Namen in Basisklassen gibt.

In Sprachen wie PHP und C # bieten Schnittstellen ein Mittel, um einen ähnlichen Polymorphismus zu erzielen, obwohl ich es nicht gerne als "Vererbung" bezeichne, da es einen konzeptionellen Unterschied zwischen der Vererbung einer abstrakten Klasse und der Implementierung einer Schnittstelle gibt. Schnittstellen beseitigen das Konfliktproblem, da sie selbst keine Implementierung bieten.

Eine Schnittstelle dient als Vertrag für die Außenwelt, während eine abstrakte Klasse eine Implementierung bereitstellen kann. Wenn sie jedoch zum "Fälschen" einer Schnittstelle verwendet wird, wird dies höchstwahrscheinlich nicht der Fall sein.

Der hauptsächliche konzeptionelle Unterschied besteht darin, dass, wenn eine Klasse eine andere Klasse erbt (abstrakt oder nicht), eine Beziehung von "ist" besteht, also Carist a ein Vehicleund Dogist ein Animal. Bei einer Schnittstelle kommt es darauf an, was das Objekt tut. Also beide Carund Dogkönnen Move()und der Verbraucher weiß es, weil sie implementieren Movable, aber ein Auto ist definitiv kein Dogoder Animal. Und die Bewegungsimplementierung wird anders sein (Räder gegen Beine), aber der konsumierende Code ist und sollte sich nicht darum kümmern. Bei Schnittstellen dreht sich alles um den konsumierenden Code und nicht um die Implementierung.

Der wichtigste Punkt ist, wenn Sie Schnittstellen in der Sprache Ihrer Wahl haben, verwenden Sie diese für Dinge, für die sie da sind. Wenn nicht (wie in C ++), können Sie sie mit reinen abstrakten Klassen fälschen.

Ivan Pintar
quelle
Die Schnittstelle ist ebenfalls ein Typ, sodass Sie ein IAnimal haben können, das beide Dogund Cat sind .
Amy Blankenship
Sie könnten, aber meiner Meinung nach geht es bei Schnittstellen um Verhalten, das der Außenwelt ausgesetzt ist, und nicht so sehr um das, was die Objekte sind. Vererbung impliziert, dass etwas eine Art von etwas anderem ist (Katze ist ein Tier). Eine Schnittstelle sagt nur, was dieses Objekt tun kann. Deshalb möchte ich sagen, dass etwas eine Schnittstelle "implementiert" und nicht "erbt", was die meisten .Net-Leute, mit denen ich gearbeitet habe, sagen würden (ich denke, weil die Syntax für Vererbung und Implementierung dieselbe ist).
Ivan Pintar
2

Abstrakte Klassen können abstrakt geschützte Methoden enthalten (in den Sprachen, mit denen ich arbeite). In Schnittstellen sind Methoden normalerweise immer öffentlich. Ob dieser Unterschied nützliche Ausbeutungen zulässt, weiß ich nicht.

Bearbeiten Ich dachte zuerst, dass eine private abstrakte Methode keinen Nutzen hat, aber jetzt erinnerte ich mich, dass sie verwendet werden kann, um sicherzustellen, dass diese Methode niemals aufgerufen wird. Auf diese Weise können Sie verhindern, dass ein Kopierkonstruktor eines Objekts aufgerufen wird.

Thomas
quelle
1
Geschützte virtuelle (überschreibbare) Methoden können für Klassen nützlich sein, die Teil eines Frameworks oder dergleichen sind. Auf diese Weise stellen sie sicher, dass der benutzerdefinierte Code in einer Klasse, die das Abstract erbt, diese Funktionalität bietet. Dies kann jedoch auch erreicht werden, indem eine Schnittstelle für die Basisklasse geerbt wird, deren Methoden jedoch nicht implementiert werden
Ivan Pintar,
Ja, ich habe über so etwas nachgedacht, habe aber keine Erfahrung damit und konnte es nicht beurteilen. Danke für die Eingabe.
Thomas
Nur eine Notiz. In einigen Sprachen können private virtuelle Methoden in abgeleiteten Klassen überschrieben werden.
Johan Boulé
2

Ja, sie sind unterschiedlich. Andernfalls hätten die Sprachdesigner nicht beides bereitgestellt. Ich kenne zwei Sprachen, die Klassen und Schnittstellen trennen: Java und C #, mutierter Klon von Java. Die Designer haben Schnittstellen erstellt, um die Unterstützung der Vererbung mehrerer Klassen zu vermeiden. Die meisten anderen Sprachen unterstützen die Vererbung mehrerer Klassen und trennen daher keine Klassen und Schnittstellen.

Kevin Cline
quelle
2

Ich denke, der Hauptunterschied besteht darin, dass: In einer abstrakten Klasse - selbst wenn alle Methoden abstrakt sind, können sie den Klassen, die sie implementieren (in Form von privaten Methoden oder Konstruktoren), Datenelemente (Instanzvariablen) und Code bereitstellen; statische Blöcke; einen Teil der Arbeit für die Unterklassen erledigen und ihnen bei der Implementierung helfen.

Ein positiver Nebeneffekt: Code befindet sich an einer Stelle, sodass Korrekturen vorgenommen werden können. Unterklassen können einfach die Superklassenmethode aufrufen und dann etwas anderes oder nichts tun, wenn Superklassenaktionen für ihren Fall ausreichen. Die Superklasse möchte, dass jede Unterklasse diese Entscheidung trifft, hat also ihre gesamte Implementierung als abstrakt markiert (einige könnten auch leer sein).

Nicht relevant für die Frage: Wenn jedoch Schnittstellen vorhanden sind, kann eine Klasse zwei verschiedene Verträge implementieren. Das ist also ein Vorteil einer Schnittstelle gegenüber einer abstrakten Superklasse

tgkprog
quelle
1
Sind abstrakte Methoden nicht ohne Implementierung definiert und überlassen Sie die Implementierung den ererbenden Klassen?
Ivan Pintar
Ja, Ihr Recht, dann denke ich, es sind nur die Variablen, Konstruktoren und statischen und privaten Methoden, wenn Sie diese zählen
tgkprog
@Pinetree, in der Praxis möchten Sie meistens mindestens ein wenig "echten" Code in Ihren Abstract-Klassen (zumindest in der von mir verwendeten Sprache, die kein spezielles Konstrukt für Abstract-Klassen enthält).
Amy Blankenship
@ AmyBlankenship Ja, die meisten abstrakten Klassen haben "echten" Code (dafür sind sie da). Ich bezog mich jedoch auf abstrakte Methoden im Kontext einer rein abstrakten Klasse, die als Schnittstelle in einer Sprache wie C ++ dient, die keine Schnittstellen hat.
Ivan Pintar