Interface vs Abstract Class (allgemeines OO)


1413

Ich hatte kürzlich zwei Telefoninterviews, in denen ich nach den Unterschieden zwischen einer Interface- und einer Abstract-Klasse gefragt wurde. Ich habe jeden Aspekt von ihnen erklärt, an den ich denken könnte, aber es scheint, dass sie darauf warten, dass ich etwas Bestimmtes erwähne, und ich weiß nicht, was es ist.

Aus meiner Erfahrung denke ich, dass das Folgende wahr ist. Wenn mir ein wichtiger Punkt fehlt, lassen Sie es mich bitte wissen.

Schnittstelle:

Jede einzelne in einer Schnittstelle deklarierte Methode muss in der Unterklasse implementiert werden. In einer Schnittstelle können nur Ereignisse, Delegaten, Eigenschaften (C #) und Methoden vorhanden sein. Eine Klasse kann mehrere Schnittstellen implementieren.

Abstrakte Klasse:

Nur abstrakte Methoden müssen von der Unterklasse implementiert werden. Eine abstrakte Klasse kann normale Methoden mit Implementierungen haben. Abstrakte Klassen können neben Ereignissen, Delegaten, Eigenschaften und Methoden auch Klassenvariablen enthalten. Eine Klasse kann nur eine abstrakte Klasse implementieren, da in C # keine Mehrfachvererbung vorhanden ist.

  1. Nach all dem stellte der Interviewer die Frage: "Was wäre, wenn Sie eine abstrakte Klasse mit nur abstrakten Methoden hätten? Wie würde sich das von einer Schnittstelle unterscheiden?" Ich wusste die Antwort nicht, aber ich denke, es ist das Erbe, wie oben erwähnt, oder?

  2. Ein anderer Interviewer fragte mich, was wäre, wenn Sie eine öffentliche Variable in der Benutzeroberfläche hätten, wie würde sich das von der abstrakten Klasse unterscheiden? Ich habe darauf bestanden, dass Sie keine öffentliche Variable in einer Schnittstelle haben können. Ich wusste nicht, was er hören wollte, aber er war auch nicht zufrieden.

Siehe auch :


412
Obwohl ich denke, dass es wichtig ist, den Unterschied zwischen den beiden zu kennen, ist dies keine gute Interviewfrage, imo. Es sei denn, der Job schrieb ein Buch über OO-Themen. Du bist besser dran, wenn du nicht für diese Ding Fledermäuse arbeitest.
Alan

107
@Alan: Ich mag das eigentlich als Interviewfrage, aber ich würde niemanden so verfolgen - ich würde es wahrscheinlich eher wie "Wo würden Sie eine Schnittstelle gegenüber einer abstrakten Basisklasse wählen, wenn Sie eine Hierarchie definieren?" ", oder etwas ähnliches.
Reed Copsey

11
Vielleicht waren sie nach einer designorientierteren Antwort ... obwohl ich sie wie Sie als technische Frage behandelt hätte.
CurtainDog

16
Schöne tabellarische Unterschiede hier: mindprod.com/jgloss/interfacevsabstract.html
Rajat_R

30
@Kave: I insisted you can't have a public variable inside an interface.Ich denke, Schnittstelle kann öffentliche Variable haben. Tatsächlich sind Variablen in der Schnittstelle automatisch öffentlich und endgültig.
ein Lernender

Antworten:


746

Während Ihre Frage angibt, dass es sich um "allgemeines OO" handelt, scheint sie sich wirklich auf die Verwendung dieser Begriffe in .NET zu konzentrieren.

In .NET (ähnlich für Java):

  • Schnittstellen können keinen Status oder keine Implementierung haben
  • Eine Klasse, die eine Schnittstelle implementiert, muss eine Implementierung aller Methoden dieser Schnittstelle bereitstellen
  • abstrakte Klassen können Status (Datenelemente) und / oder Implementierung (Methoden) enthalten.
  • abstrakte Klassen können ohne Implementierung der abstrakten Methoden vererbt werden (obwohl eine solche abgeleitete Klasse selbst abstrakt ist)
  • Schnittstellen können mehrfach vererbt sein, abstrakte Klassen möglicherweise nicht (dies ist wahrscheinlich der konkrete Hauptgrund dafür, dass Schnittstellen getrennt von abstrakten Klassen existieren - sie ermöglichen die Implementierung einer Mehrfachvererbung, die viele der Probleme des allgemeinen MI beseitigt).

Als allgemeine OO-Begriffe sind die Unterschiede nicht unbedingt genau definiert. Beispielsweise gibt es C ++ - Programmierer, die möglicherweise ähnliche starre Definitionen haben (Schnittstellen sind eine strikte Teilmenge abstrakter Klassen, die keine Implementierung enthalten können), während einige sagen, dass eine abstrakte Klasse mit einigen Standardimplementierungen immer noch eine Schnittstelle oder eine nicht abstrakte ist Klasse kann weiterhin eine Schnittstelle definieren.

In der Tat gibt es eine C ++ - Redewendung namens Non-Virtual Interface (NVI), bei der die öffentlichen Methoden nicht virtuelle Methoden sind, die sich auf private virtuelle Methoden beziehen:


7
Vielen Dank. Ich denke, da Ihre Antwort den Zustand + einen guten Überblick über alle anderen erwähnt, markiere ich Ihre Antwort als endgültige Antwort. Sie haben Recht, ich habe nach allgemeinem OO gefragt, da mein erster Interviewer nach allgemeinem OO gefragt hat, aber da ich ein C # -Typ bin, neige ich dazu, das zu vergessen. ;-) Danke auch für die C ++ Erklärung, wie immer ist C ++ umwerfend.
Houman

6
Ich denke, ein wichtiger Punkt in der Erklärung, die Michael gegeben hat, ist, dass Sie beim Implementieren einer Schnittstelle alle Mitglieder in der Schnittstelle implementieren MÜSSEN, aber wenn Sie von einer abstrakten Klasse erben, ist es von einer untergeordneten Klasse NICHT ERFORDERLICH, die Mitglieder ihrer Eltern zu implementieren
Guillermo Gomez

82
+1: Ich würde wetten, dass die Affen, die das Interview veranstalten, nicht einmal erkennen, dass andere Sprachen OO anders implementieren.
Leichtigkeitsrennen im Orbit

2
@ JL Ich sehe nicht, wo das Problem liegt. Sie scheinen die abstrakte Methode mit der abstrakten Klasse verwechselt zu haben. Abstrakte Methoden haben keine Implementierung. Innerhalb einer abstrakten Klasse können jedoch einige Methoden abstrakt sein (dh ohne Implementierung), während andere tatsächlich implementiert werden können.
Xji

19
Beachten Sie, dass Sie in Java 8 jetzt Standardmethoden und statische Methoden in Schnittstellen haben können, was bedeutet, dass Java-Schnittstellen implementiert werden können. Referenz hier . Offensichtlich haben Sie sich hauptsächlich auf .NET bezogen, dies ist also nur eine Beobachtung, die sich auf Java bezieht.
Davvtom

866

Wie wäre es mit einer Analogie: Als ich in der Luftwaffe war, ging ich zur Pilotenausbildung und wurde Pilot der USAF (US Air Force). Zu diesem Zeitpunkt war ich nicht zum Fliegen qualifiziert und musste an einem Flugzeugtypentraining teilnehmen. Nach meiner Qualifikation war ich Pilot (Abstract-Klasse) und C-141-Pilot (Betonklasse). Bei einem meiner Aufträge erhielt ich eine zusätzliche Aufgabe: Sicherheitsbeauftragter. Jetzt war ich noch Pilot und C-141-Pilot, aber ich habe auch Aufgaben als Sicherheitsbeauftragter wahrgenommen (ich habe sozusagen ISafetyOfficer implementiert). Ein Pilot musste kein Sicherheitsbeauftragter sein, andere Leute hätten es auch tun können.

Alle USAF-Piloten müssen bestimmte luftwaffenweite Vorschriften befolgen, und alle C-141- (oder F-16- oder T-38-) Piloten sind USAF-Piloten. Jeder kann Sicherheitsbeauftragter sein. Um es zusammenzufassen:

  • Pilot: abstrakte Klasse
  • C-141 Pilot: Betonklasse
  • Sicherheitsbeauftragter: Schnittstelle

Hinweis hinzugefügt: Dies sollte eine Analogie zur Erläuterung des Konzepts sein, keine Kodierungsempfehlung. Siehe die verschiedenen Kommentare unten, die Diskussion ist interessant.


87
Ich mag diese Analogie sehr, sie verwendet ein einfaches Beispiel, um ein etwas komplexes Thema zu erklären
Kevin Bowersox

13
Dies ist der beste Weg, um die komplexe OO-Terminologie zu verstehen. Kurz gesagt, jede Theorie ist nur dann wert, wenn Sie sie praktisch nutzen können. @ Jay Sie rexample ist wirklich leicht zu erfassen, dann mehrere Aufzählungspunkte (meistens durchdringende Geist, anstatt absorbiert zu werden!)
vs

54
Ich bin immer noch ein bisschen verwirrt. Angenommen, Sie haben jetzt die Qualifikationen F-16 und T-38, sodass die Klasse jetzt Jaynicht mehr von mehreren Klassen (C-141-Pilot, F-16-Pilot und T-38-Pilot) erben kann. Bedeutet das, dass deren Klassen zu Schnittstellen werden sollten? Vielen Dank
Alex Okrushko

37
Viele Leute haben Alex 'Kommentar zu Recht mit +1 bewertet, da dies in diesem Beispiel eine gewisse Schwäche aufzeigt. Zunächst würde ich sagen, dass Jay eher eine Instanz von C-141Pilot als eine eigene Klasse wäre. Da in der USAF 99% aller Piloten jeweils nur in einem Flugzeug qualifiziert sind (FCF- und Testpiloten sind bemerkenswerte Ausnahmen), habe ich nicht über mehrere Qualifikationen nachgedacht und wie diese implementiert werden könnten. Da ich von einem Piloten weiß, der vor 50 Jahren gleichzeitig in 25 verschiedenen Flugzeugen qualifiziert war, denke ich, dass dies ein Beispiel dafür ist, wie wir KEINE Mehrfachvererbung verwenden wollen.
Jay

20
Da es unwahrscheinlich ist, dass ein Pilot mehr als ein Flugzeug gleichzeitig fliegt, wäre dies eine gute Gelegenheit, das Strategiemuster umzusetzen. Ein Pilot verfügt über eine Sammlung von Zertifizierungen und wählt zur Laufzeit die richtige aus. Die Zertifizierungen würden als Verhaltensweisen codiert, die die IFlyPlane-Schnittstelle mit den Methoden TakeOff, Land, Eject implementieren würden.
Michael Blackburn

221

Ich denke, die Antwort, nach der sie suchen, ist der grundlegende oder OPPS-philosophische Unterschied.

Die Vererbung abstrakter Klassen wird verwendet, wenn die abgeleitete Klasse die Kerneigenschaften und das Verhalten der abstrakten Klasse gemeinsam nutzt. Die Art von Verhalten, die die Klasse tatsächlich definiert.

Andererseits wird die Schnittstellenvererbung verwendet, wenn die Klassen das periphere Verhalten gemeinsam haben, das die abgeleitete Klasse nicht unbedingt definiert.

Zum Beispiel. Ein Auto und ein LKW teilen viele Kerneigenschaften und das Verhalten einer abstrakten Klasse für Automobile, aber sie teilen auch ein peripheres Verhalten wie Abgas erzeugen, das selbst Nicht-Auto-Klassen wie Bohrer oder PowerGeneratoren gemeinsam haben und nicht unbedingt ein Auto oder einen LKW definieren So können Auto, LKW, Bohrer und PowerGenerator alle dieselbe Schnittstelle IExhaust gemeinsam nutzen.


32
Ich denke, eine noch bessere Analogie wäre "usedFuel", die den Vertragscharakter der Schnittstelle zeigen würde .
Pureferret

@Pureferret Wenn acceleratees Teil des Kernverhaltens der abstrakten Klasse von Automobile ist, kann ich nicht sagen accelerate, dass es den Vertragscharakter zeigt . Was ist Vertragscharakter? Warum wurde dieses Wort contracteingeführt, wenn wir darüber sprechen interface?
Überaustausch

@overexchange, da sich die Schnittstelle normalerweise nur dort befindet, wo sich zwei 'Oberflächen' treffen, aber das Wort Vertrag impliziert, dass eine Übereinstimmung darüber besteht, wie sich die beiden 'Oberflächen' treffen. Es macht (zumindest für mich) keinen Sinn, dass die Erzeugung von Abgasen etwas ist, worüber Sie sich einig sind. Aber es macht (wieder für mich) Sinn, dass Sie sich darauf einigen können, Kraftstoff verwenden zu müssen.
Pureferret

1
@ Pureferret Ich habe eine Anfrage unter Link für das gleiche gestellt
Überaustausch

1
@Pureferret Wenn interfaceperipheres Verhalten erforderlich ist , warum public interface List<E> extends Collection<E> {}soll dann das Kernverhalten von beschrieben werden list? Dies widerspricht tatsächlich der Antwort von Prasun. Beide Collection<E>und List<E>sind hier Schnittstellen.
Überaustausch

198

Kurz: Abstrakte Klassen werden zum Modellieren einer Klassenhierarchie ähnlich aussehender Klassen verwendet (z. B. Tier kann abstrakte Klasse sein und Mensch, Löwe, Tiger können konkrete abgeleitete Klassen sein).

UND

Die Schnittstelle wird für die Kommunikation zwischen zwei ähnlichen / nicht ähnlichen Klassen verwendet, wobei der Typ der Klasse, die die Schnittstelle implementiert, keine Rolle spielt (z. B. Höhe kann eine Schnittstelleneigenschaft sein und kann von Mensch, Gebäude, Baum implementiert werden. Es spielt keine Rolle, ob Sie essen können , du kannst schwimmen, du kannst sterben oder so .. es ist nur eine Sache, die du brauchst, um Höhe zu haben (Implementierung in deiner Klasse)).


7
Ich mag diese Antwort wirklich, weil es manchmal schwierig ist, das "Was" zwischen den Dingen zu beantworten, indem man etwas Abstrakteres wie Absicht betrachtet , anstatt nur Struktur (da strukturell eine Schnittstelle und eine reine abstrakte Klasse ziemlich gleich sind Ding).
LostSalad

Es ist einfach aufzuzählen, was eine abstrakte Klasse im Vergleich zu einer Schnittstelle in einer bestimmten Sprache tun kann, aber es ist schwieriger, eine Abstraktion zu erstellen, um dem Objekt Bedeutung und Verantwortung zu verleihen, und was Sie gesagt haben, setzt die Verwendung des 2-Konzepts in OO vollständig fort. Vielen Dank!
Samuel

2
@dhananjay: Ich sehe, wie Höhe vom Konzept der Tierklasse getrennt und von einer anderen Klasse sein kann, aber was genau meinst du mit "Kommunikation" zwischen den Klassen? Es definiert einfach nur die Höhe für seine eigene Klasse, richtig?
TTT

77

Es gibt noch ein paar andere Unterschiede -

Schnittstellen können keine konkreten Implementierungen haben. Abstrakte Basisklassen können. Auf diese Weise können Sie dort konkrete Implementierungen vornehmen. Dies kann es einer abstrakten Basisklasse ermöglichen, tatsächlich einen strengeren Vertrag bereitzustellen, wobei eine Schnittstelle wirklich nur beschreibt, wie eine Klasse verwendet wird. (Die abstrakte Basisklasse kann nicht virtuelle Mitglieder haben, die das Verhalten definieren, wodurch der Autor der Basisklasse mehr Kontrolle erhält.)

In einer Klasse kann mehr als eine Schnittstelle implementiert werden. Eine Klasse kann nur von einer einzelnen abstrakten Basisklasse abgeleitet werden. Dies ermöglicht eine polymorphe Hierarchie unter Verwendung von Schnittstellen, jedoch keine abstrakten Basisklassen. Dies ermöglicht auch eine Pseudo-Multi-Vererbung unter Verwendung von Schnittstellen.

Abstrakte Basisklassen können in v2 + geändert werden, ohne die API zu beschädigen. Änderungen an Schnittstellen sind wichtige Änderungen.

[C # /. NET-spezifisch] Schnittstellen können im Gegensatz zu abstrakten Basisklassen auf Werttypen (Strukturen) angewendet werden. Strukturen können nicht von abstrakten Basisklassen erben. Dadurch können Verhaltensverträge / Nutzungsrichtlinien auf Werttypen angewendet werden.


5
+1 für den Schlüsselpunkt, dass mehr als eine Schnittstelle in einer Klasse implementiert werden kann.
CGP

Das ist der einzige wirkliche Vorteil von Schnittstellen gegenüber abstrakten Basisklassen, IMO. Ansonsten stimme ich den .NET-Designrichtlinien zu, die jetzt besagen, "abstrakte Basisklassen gegenüber Schnittstellen zu bevorzugen"
Reed Copsey

Es wäre jedoch sehr interessant, wenn Sie den Punkt hinzufügen könnten, dass die Schnittstellen auch auf jede Klasse angewendet werden können.
CGP

1
@altCognito: Ich dachte, das wurde mit dem zweiten Absatz behandelt. Dies hat mich jedoch daran erinnert, dass Schnittstellen mit Werttypen funktionieren, also habe ich das hinzugefügt.
Reed Copsey

Vielen Dank für diese genaue Beschreibung. Es ist in der Tat sehr hilfreich. Ich bin neu hier. Schade, dass Sie nicht zwei Antworten als "Antwort" auswählen können. Eine Sache, die mich verwirrt, ist Ihre Verwendung der abstrakten 'Basis'-Klasse. Alle abstrakten Klassen sollen eine Basisklasse einer Unterklasse sein. Warum die 'Basis' extra benennen?
Houman

68

Vererbung
Betrachten Sie ein Auto und einen Bus. Sie sind zwei verschiedene Fahrzeuge. Trotzdem haben sie einige gemeinsame Eigenschaften wie Lenkung, Bremsen, Getriebe, Motor usw.
Mit dem Vererbungskonzept kann dies wie folgt dargestellt werden ...

public class Vehicle {
    private Driver driver;
    private Seat[] seatArray; //In java and most of the Object Oriented Programming(OOP) languages, square brackets are used to denote arrays(Collections).
    //You can define as many properties as you want here ...
}

Jetzt ein Fahrrad ...

public class Bicycle extends Vehicle {
    //You define properties which are unique to bicycles here ...
    private Pedal pedal;
}

Und ein Auto ...

public class Car extends Vehicle {
    private Engine engine;
    private Door[] doors;
}

Das ist alles über Vererbung . Wir verwenden sie, um Objekte in einfachere Basisformen und ihre Kinder zu klassifizieren, wie wir oben gesehen haben.

Abstrakte Klassen

Abstrakte Klassen sind unvollständige Objekte. Um es besser zu verstehen, betrachten wir noch einmal die Fahrzeuganalogie.
Ein Fahrzeug kann gefahren werden. Recht? Aber verschiedene Fahrzeuge werden auf unterschiedliche Weise gefahren ... Zum Beispiel können Sie ein Auto nicht so fahren, wie Sie ein Fahrrad fahren.
Wie kann man also die Antriebsfunktion eines Fahrzeugs darstellen? Es ist schwieriger zu überprüfen, um welchen Fahrzeugtyp es sich handelt, und es mit einer eigenen Funktion zu fahren. Sie müssten die Fahrerklasse immer wieder ändern, wenn Sie einen neuen Fahrzeugtyp hinzufügen.
Hier kommt die Rolle abstrakter Klassen und Methoden. Sie können die Laufwerksmethode als abstrakt definieren, um anzugeben, dass alle ererbenden untergeordneten Elemente diese Funktion implementieren müssen.
Also, wenn Sie die Fahrzeugklasse ändern ...

//......Code of Vehicle Class
abstract public void drive();
//.....Code continues

Das Fahrrad und das Auto müssen auch angeben, wie es zu fahren ist. Andernfalls wird der Code nicht kompiliert und es wird ein Fehler ausgegeben.
Kurz gesagt ... eine abstrakte Klasse ist eine teilweise unvollständige Klasse mit einigen unvollständigen Funktionen, die die ererbenden Kinder selbst angeben müssen.

Schnittstellen Schnittstellen sind völlig unvollständig. Sie haben keine Eigenschaften. Sie zeigen nur an, dass die erbenden Kinder in der Lage sind, etwas zu tun ...
Angenommen, Sie haben verschiedene Arten von Mobiltelefonen bei sich. Jeder von ihnen hat verschiedene Möglichkeiten, verschiedene Funktionen auszuführen. Beispiel: Rufen Sie eine Person an. Der Hersteller des Telefons gibt an, wie es geht. Hier können die Mobiltelefone eine Nummer wählen - das heißt, sie können gewählt werden. Stellen wir dies als Schnittstelle dar.

public interface Dialable {
    public void dial(Number n);
}

Hier definiert der Hersteller des Wählbaren, wie eine Nummer gewählt wird. Sie müssen ihm nur eine Nummer zum Wählen geben.

// Makers define how exactly dialable work inside.

Dialable PHONE1 = new Dialable() {
    public void dial(Number n) {
        //Do the phone1's own way to dial a number
    }
}

Dialable PHONE2 = new Dialable() {
    public void dial(Number n) {
        //Do the phone2's own way to dial a number
    }
}


//Suppose there is a function written by someone else, which expects a Dialable
......
public static void main(String[] args) {
    Dialable myDialable = SomeLibrary.PHONE1;
    SomeOtherLibrary.doSomethingUsingADialable(myDialable);
}
.....

Bei der Verwendung von Schnittstellen anstelle von abstrakten Klassen muss sich der Verfasser der Funktion, die ein Wählbares verwendet, nicht um seine Eigenschaften kümmern. Beispiel: Hat es einen Touchscreen oder eine Wähltastatur? Ist es ein Festnetztelefon oder ein Mobiltelefon? Sie müssen nur wissen, ob es wählbar ist. erbt (oder implementiert) es die wählbare Schnittstelle?

Und was noch wichtiger ist , wenn Sie eines Tages die Wählscheibe gegen eine andere austauschen

......
public static void main(String[] args) {
    Dialable myDialable = SomeLibrary.PHONE2; // <-- changed from PHONE1 to PHONE2
    SomeOtherLibrary.doSomethingUsingADialable(myDialable);
}
.....

Sie können sicher sein, dass der Code immer noch einwandfrei funktioniert, da die Funktion, die das Wählbare verwendet, nicht (und nicht) von anderen als den in der Wählschnittstelle angegebenen Details abhängt. Beide implementieren eine wählbare Schnittstelle und das ist das einzige, was die Funktion interessiert.

Schnittstellen werden häufig von Entwicklern verwendet, um die Interoperabilität (austauschbare Verwendung) zwischen Objekten sicherzustellen, sofern diese eine gemeinsame Funktion haben (genau wie Sie zu einem Festnetz- oder Mobiltelefon wechseln können, sofern Sie nur eine Nummer wählen müssen). Kurz gesagt, Schnittstellen sind eine viel einfachere Version von abstrakten Klassen ohne Eigenschaften.
Beachten Sie außerdem, dass Sie so viele Schnittstellen implementieren (erben) können, wie Sie möchten, aber nur eine einzelne übergeordnete Klasse erweitern (erben) dürfen.

Weitere Info Abstract Klassen vs Interfaces


Es ist nicht wahr, dass "Schnittstellen keine Eigenschaften haben".
Großaugen

@Bigeyes, Java erlaubt keine Eigenschaften in Schnittstellen. Ich dachte, dass es auch in anderen Sprachen so ist. Könnten Sie bitte mehr erklären?
fz_salam

Ich beziehe mich auf C # /. Net. Bitte sehen Sie das Beispiel
Großaugen

@Bigeyes für C #, wo Schnittstellen Eigenschaften haben können, führt dies nicht wieder zu dem Problem der Mehrfachvererbung? Was passiert, wenn eine Klasse mehrere Schnittstellen verwendet, die dieselbe Eigenschaft definiert haben? Nur neugierig danke
stackPusher

@happycoder: re: "Wenn Sie hier Schnittstellen anstelle von abstrakten Klassen verwenden, müssen Sie sich keine Gedanken über deren Eigenschaften machen. Beispiel: Verfügt es über einen Touchscreen oder eine Wähltastatur? Ist es ein Festnetztelefon oder ein Mobiltelefon? Sie müssen nur wissen, ob es wählbar ist; erbt (oder implementiert) es die wählbare Schnittstelle. " - Können Sie dies in einem Codebeispiel zeigen, haben Sie auch nicht gesehen, wie es vererbt werden würde ...
TTT

45

Wenn Sie javadiese Frage als OOP-Sprache beantworten, führt die Java 8-Version dazu, dass einige der in den obigen Antworten enthaltenen Inhalte veraltet sind. Jetzt kann die Java-Schnittstelle Standardmethoden mit konkreter Implementierung haben.

Die Oracle- Website bietet wichtige Unterschiede zwischen interfaceund abstractKlasse.

Verwenden Sie abstrakte Klassen, wenn:

  1. Sie möchten Code für mehrere eng verwandte Klassen freigeben.
  2. Sie erwarten, dass Klassen, die Ihre abstrakte Klasse erweitern, über viele gängige Methoden oder Felder verfügen oder andere als öffentliche (z. B. geschützte und private) Zugriffsmodifikatoren erfordern.
  3. Sie möchten nicht statische oder nicht endgültige Felder deklarieren.

Erwägen Sie die Verwendung von Schnittstellen, wenn:

  1. Sie erwarten, dass nicht verwandte Klassen Ihre Schnittstelle implementieren. Beispielsweise können viele nicht verwandte Objekte eine SerializableSchnittstelle implementieren .
  2. Sie möchten das Verhalten eines bestimmten Datentyps angeben, sind jedoch nicht darüber besorgt, wer sein Verhalten implementiert.
  3. Sie möchten die Mehrfachvererbung des Typs nutzen.

In einfachen Worten möchte ich verwenden

Schnittstelle: Um einen Vertrag durch mehrere unabhängige Objekte zu implementieren

abstrakte Klasse: Um dasselbe oder ein unterschiedliches Verhalten zwischen mehreren verwandten Objekten zu implementieren

Schauen Sie sich das Codebeispiel an, um die Dinge klar zu verstehen: Wie hätte ich den Unterschied zwischen einer Interface- und einer Abstract-Klasse erklären sollen?


33

Die Interviewer bellen einen seltsamen Baum an. Für Sprachen wie C # und Java gibt es einen Unterschied, für andere Sprachen wie C ++ jedoch keinen. Die OO-Theorie unterscheidet die beiden nicht, sondern lediglich die Syntax der Sprache.

Eine abstrakte Klasse ist eine Klasse mit Implementierung und Schnittstelle (reine virtuelle Methoden), die vererbt werden. Schnittstellen haben im Allgemeinen keine Implementierung, sondern nur reine virtuelle Funktionen.

In C # oder Java unterscheidet sich eine abstrakte Klasse ohne Implementierung von einer Schnittstelle nur in der Syntax, die zum Erben verwendet wird, und in der Tatsache, dass Sie nur von einer erben können.


Vor einer Woche wurde mir dieselbe Frage gestellt. Ich habe keine Erfahrung mit Java, arbeite aber jetzt schon eine Weile mit C ++. Der Interviewer hat vor dem Stellen der Frage keine Sprachen angegeben, daher habe ich nur erklärt, dass Schnittstellen in diesem Fall abstrakte Klassen ohne Status oder Implementierungen jeglicher Art sind. Ich stimme zu, dass es auch eine seltsame Frage ist.
Dacabdi

31

Durch die Implementierung von Schnittstellen erreichen Sie eine Komposition ("has-a" -Beziehungen) anstelle einer Vererbung ("is-a" -Beziehungen). Dies ist ein wichtiges Prinzip, an das Sie sich erinnern sollten, wenn es um Entwurfsmuster geht, bei denen Sie Schnittstellen verwenden müssen, um eine Komposition von Verhaltensweisen anstelle einer Vererbung zu erzielen.


17
Schnittstellen erreichen, IMO, eher eine "Acts-as-a" -Beziehung. Die Kapselung erzielt eine bessere Komposition als eine Schnittstelle.
Reed Copsey

12
Ich glaube nicht, dass die Implementierung von Schnittstellen unter die Zusammensetzung fallen würde.
Pavan Dittakavi

Außerdem wird die Schnittstelle eher verwendet, um "Fähigkeiten" wie IDisposable zu beschreiben. Früher teilte es die Funktionalität zwischen Klassen, dass diese Klassen etwas "können". Weitere Beispiele IFlyable können von Vogel und Flugzeug implementiert werden. Aber Bird kann von Class Creature stammen, wo Flugzeuge von AirCraft stammen.
Peter.Wang

26

Ich werde die Details der Schnittstelle und der abstrakten Klasse erläutern. Wenn Sie einen Überblick über die Schnittstelle und die abstrakte Klasse haben, stellen Sie sich zunächst die Frage, wann wir die Schnittstelle und wann wir die abstrakte Klasse verwenden sollten. Bitte überprüfen Sie die unten stehende Erklärung der Interface- und Abstract-Klasse.

  1. Wann sollten wir Interface verwenden?

    Wenn Sie nicht über die Implementierung Bescheid wissen, nur wir haben Anforderungsspezifikationen, dann gehen wir mit Schnittstelle

  2. Wann sollten wir Abstract Class verwenden?

    Wenn Sie die Implementierung kennen, aber nicht vollständig (teilweise Implementierung), dann gehen wir mit der Abstract-Klasse.

    Schnittstelle

    Standardmäßig bedeutet jede Methode public abstract, dass die Schnittstelle zu 100% rein abstrakt ist.

    Abstrakt

    kann eine konkrete Methode und eine abstrakte Methode haben, was eine konkrete Methode ist, die in der abstrakten Klasse implementiert ist. Eine abstrakte Klasse ist eine Klasse, die als abstrakt deklariert ist - sie kann abstrakte Methoden enthalten oder nicht.

    Schnittstelle

    Wir können die Schnittstelle nicht als privat und geschützt deklarieren

    Q. Warum erklären wir Interface nicht als privat und geschützt?

    Da die Schnittstellenmethode standardmäßig öffentlich abstrakt ist, deklarieren wir die Schnittstelle nicht als privat und geschützt.

    Schnittstellenmethode
    Wir können die Schnittstelle auch nicht als privat, geschützt, endgültig, statisch, synchronisiert, nativ deklarieren.

    Ich werde den Grund angeben: Warum wir keine synchronisierte Methode deklarieren, weil wir kein Objekt der Schnittstelle erstellen und synchronisieren können, sind Arbeiten am Objekt, und der Grund, warum wir die synchronisierte Methode nicht deklarieren, ist auch nicht anwendbar, weil transiente Arbeit mit synchronisierten Methoden.

    Abstrakt

    Wir verwenden gerne öffentliche, private endgültige statische Elemente. Dies bedeutet, dass abstrakte Einschränkungen nicht gelten.

    Schnittstelle

    Variablen werden in Interface standardmäßig als öffentliches statisches Finale deklariert, sodass wir auch nicht als private, geschützte Variable deklariert werden.

    Der flüchtige Modifikator ist auch in der Schnittstelle nicht anwendbar, da die Schnittstellenvariable standardmäßig eine öffentliche statische endgültige und endgültige Variable ist. Sie können den Wert nicht ändern, sobald der Wert der Variablen zugewiesen wurde und wenn Sie die Variable der Schnittstelle deklariert haben, müssen Sie die Variable zuweisen.

    Und die flüchtige Variable ändert sich ständig, so dass sie entgegengesetzt ist. Aus diesem Grund verwenden wir keine flüchtige Variable in der Schnittstelle.

    Abstrakt

    Abstrakte Variable muss nicht als öffentliches statisches Finale deklariert werden.

Ich hoffe, dieser Artikel ist nützlich.


4
Ich bin mit diesem Punkt nicht einverstanden: Abstract class must have at lease one abstract method.Es ist möglich, eine Abstract-Klasse ohne eine Abstract-Methode zu haben, solange Sie sie implementieren. REFERENZ: An abstract class is a class that is declared abstract—it may or may not include abstract methods.REFERENZQUELLE: docs.oracle.com/javase/tutorial/java/IandI/abstract.html
Devner

Sie sprechen über technische Details und Implementierung, Sie beantworten die Frage nicht in Bezug auf allgemeine OOP
Billal Begueradj

26

Konzeptionell gesehen kann oder kann die Beibehaltung der sprachspezifischen Implementierung, Regeln, Vorteile und das Erreichen eines Programmierziels durch Verwendung von irgendjemandem oder beidem Code / Daten / Eigenschaften, bla bla, einzelne oder mehrere Vererbungen haben oder nicht

1- Abstrakte (oder rein abstrakte) Klasse soll Hierarchie implementieren. Wenn Ihre Geschäftsobjekte strukturell etwas ähnlich aussehen und nur eine Eltern-Kind-Beziehung (Hierarchie) darstellen, werden Vererbungs- / abstrakte Klassen verwendet. Wenn Ihr Geschäftsmodell keine Hierarchie hat, sollte die Vererbung nicht verwendet werden (hier spreche ich nicht über Programmierlogik, z. B. erfordern einige Entwurfsmuster eine Vererbung). Konzeptionell ist die abstrakte Klasse eine Methode zum Implementieren der Hierarchie eines Geschäftsmodells in OOP. Sie hat nichts mit Schnittstellen zu tun. Der Vergleich der abstrakten Klasse mit der Schnittstelle ist bedeutungslos, da beide konzeptionell völlig unterschiedliche Dinge sind. In Interviews wird nur darum gebeten, die Konzepte zu überprüfen, da beide bei der Implementierung ungefähr die gleiche Funktionalität bieten und wir Programmierer normalerweise mehr Wert auf die Codierung legen. [Denken Sie auch daran, dass sich die Abstraktion von der abstrakten Klasse unterscheidet].

2- Eine Schnittstelle ist ein Vertrag, eine vollständige Geschäftsfunktionalität, die durch eine oder mehrere Funktionen dargestellt wird. Deshalb wird es implementiert und nicht vererbt. Ein Geschäftsobjekt (Teil einer Hierarchie oder nicht) kann eine beliebige Anzahl vollständiger Geschäftsfunktionen aufweisen. Es hat nichts mit abstrakten Klassen zu tun, bedeutet Vererbung im Allgemeinen. Zum Beispiel kann ein Mensch LAUFEN, ein Elefant kann LAUFEN, ein Vogel kann LAUFEN usw. Alle diese Objekte unterschiedlicher Hierarchie würden die RUN-Schnittstelle oder die EAT- oder SPEAK-Schnittstelle implementieren. Gehen Sie nicht in die Implementierung, da Sie möglicherweise abstrakte Klassen für jeden Typ implementieren, der diese Schnittstellen implementiert. Ein Objekt jeder Hierarchie kann eine Funktionalität (Schnittstelle) haben, die nichts mit seiner Hierarchie zu tun hat.

Ich glaube, Schnittstellen wurden nicht erfunden, um Mehrfachvererbungen zu erreichen oder öffentliches Verhalten aufzudecken, und in ähnlicher Weise sollen reine abstrakte Klassen Schnittstellen nicht außer Kraft setzen, aber Schnittstelle ist eine Funktionalität, die ein Objekt (über Funktionen dieser Schnittstelle) ausführen kann, und abstrakte Klasse repräsentiert a Eltern einer Hierarchie, um Kinder mit der Kernstruktur (Eigenschaft + Funktionalität) des Elternteils zu erzeugen

Wenn Sie nach dem Unterschied gefragt werden, handelt es sich tatsächlich um einen konzeptionellen Unterschied, nicht um den Unterschied in der sprachspezifischen Implementierung, es sei denn, Sie werden ausdrücklich dazu aufgefordert.

Ich glaube, beide Interviewer hatten einen direkten Unterschied zwischen diesen beiden erwartet, und als Sie versagten, versuchten sie, Sie zu diesem Unterschied zu führen, indem sie ONE als den ANDEREN implementierten

Was wäre, wenn Sie eine abstrakte Klasse mit nur abstrakten Methoden hätten?


Das fasst die Antwort auf diese Frage ziemlich gut zusammen.
Pranavn

Funktionalität implementiert vs Struktur erweitert, schön!
Roughvchawla

21

Für .Net,

Ihre Antwort auf Der zweite Interviewer ist auch die Antwort auf den ersten ... Abstrakte Klassen können implementiert werden, UND Status, Schnittstellen können nicht ...

BEARBEITEN: In einem anderen Fall würde ich nicht einmal den Ausdruck "Unterklasse" (oder den Ausdruck "Vererbung") verwenden, um Klassen zu beschreiben, die "definiert sind, um eine Schnittstelle zu implementieren". Für mich ist eine Schnittstelle eine Definition eines Vertrags, dem eine Klasse entsprechen muss, wenn sie definiert wurde, um diese Schnittstelle zu "implementieren". Es erbt nichts ... Sie müssen alles explizit selbst hinzufügen.


2
Ja! Zustand! Das meinte der zweite Interviewer mit seiner seltsamen Art, "öffentliche Variable" innerhalb einer Schnittstelle zu sagen. Meine Güte! Abstrakte Klassen können Status haben, Schnittstellen nicht! Und ja, alle anderen sind sich auch über die Unterschiede zwischen ihren Vererbungsarten einig, die ich vergessen hatte zu erwähnen, aber bereits später herausgefunden hatte. :) Danke an alle!
Houman

4
Mehr als nur angeben ... Abstrakte Klassen können IMPLEMENTIEREN. Das heißt, sie können Methoden mit Code enthalten, die tatsächlich ausgeführt werden und etwas tun, das von Instanzen der Basisklassen geerbt und ausgeführt wird ... Nicht so bei Schnittstellen
Charles Bretana

Noch mehr als das, in gewissem Sinne, können abstrakte Klassen instanziiert werden, sie müssen nur unter Verwendung einer abgeleiteten Klassendefinition instanziiert werden, nicht direkt. In der abstrakten Klasse definierte Statusvariablen werden jedoch in dem Objekt instanziiert, das durch Neuerstellen einer Instanz der abgeleiteten Klasse erstellt wurde. Diese Instanz ist sowohl eine Instanz der abstrakten Klasse als auch eine Instanz der abgeleiteten Klasse - sie ist schließlich davon abgeleitet. Nichts davon gilt für eine Schnittstelle.
Charles Bretana

Wenn Sie eine Instanz einer Klasse neu definieren, die zum Implementieren einer Schnittstelle definiert wurde, handelt es sich nicht um eine "Instanz" dieser Schnittstelle. Die Syntax bewirkt lediglich, dass der Compiler den Code für die Klasse überprüft und sicherstellt, dass jedes Verhalten (Methode, Eigenschaft , event, eventHandler usw.), die von der Schnittstelle definiert werden, wurden im Code für die Klasse implementiert.
Charles Bretana

20

Schnittstelle : sollte verwendet werden, wenn Sie eine Regel für die Komponenten implizieren möchten, die möglicherweise miteinander in Beziehung stehen oder nicht

Vorteile:

  1. Ermöglicht Mehrfachvererbung
  2. Bietet Abstraktion, indem nicht angegeben wird, welche Art von Objekt genau im Kontext verwendet wird
  3. sorgt für Konsistenz durch eine bestimmte Vertragsunterzeichnung

Nachteile:

  1. Muss alle definierten Verträge implementieren
  2. Variablen oder Delegaten können nicht vorhanden sein
  3. Einmal definiert, kann nicht geändert werden, ohne alle Klassen zu unterbrechen

Abstrakte Klasse : sollte verwendet werden, wenn Sie ein grundlegendes oder Standardverhalten oder eine Implementierung für miteinander verbundene Komponenten wünschen

Vorteile:

  1. Schneller als die Schnittstelle
  2. Hat Flexibilität in der Implementierung (Sie können es ganz oder teilweise implementieren)
  3. Kann leicht geändert werden, ohne die abgeleiteten Klassen zu beschädigen

Nachteile:

  1. Kann nicht instanziiert werden
  2. Unterstützt keine Mehrfachvererbung

Schneller definieren. Ist es wichtig? Was bedeutet das überhaupt? Opcode für Funktionsaufruf in einer abstrakten Klasse ist schneller als Opcode für Funktionsaufruf in einer Schnittstelle?
denis631

Die abstrakte Klasse @ denis631 ist etwas schneller als die Schnittstelle, da die Such- und Aufrufmethode in der Schnittstellenmethode enthalten ist. Lesen Sie diese Datei coderanch.com/t/503450/java/abstract-class-faster-interface
Bourax Webmaster

17

Ich denke, Ihre Antwort hat ihnen nicht gefallen, weil Sie die technischen Unterschiede anstelle der gestalterischen angegeben haben. Die Frage ist für mich wie eine Trollfrage. Tatsächlich haben Schnittstellen und abstrakte Klassen eine völlig andere Natur, sodass Sie sie nicht wirklich vergleichen können. Ich werde Ihnen meine Vision geben, welche Rolle eine Schnittstelle spielt und welche Rolle eine abstrakte Klasse spielt.

Schnittstelle: Wird verwendet, um einen Vertrag sicherzustellen und eine geringe Kopplung zwischen Klassen herzustellen, um eine wartbarere, skalierbarere und testbarere Anwendung zu erhalten.

abstrakte Klasse: wird nur verwendet, um Code zwischen Klassen mit derselben Verantwortlichkeit zu faktorisieren. Beachten Sie, dass dies der Hauptgrund ist, warum Mehrfachvererbung in OOP eine schlechte Sache ist, da eine Klasse nicht mit vielen Verantwortlichkeiten umgehen sollte (verwenden Sie stattdessen die Komposition ).

Schnittstellen spielen also eine echte architektonische Rolle, während abstrakte Klassen fast nur ein Detail der Implementierung sind (wenn Sie sie natürlich richtig verwenden).


13
After all that, the interviewer came up with the question "What if you had an 
Abstract class with only abstract methods? How would that be different
from an interface?" 

Dokumente sagen eindeutig, dass eine abstrakte Klasse, die nur abstrakte Methodendeklarationen enthält, stattdessen als Schnittstelle deklariert werden sollte.

An another interviewer asked me what if you had a Public variable inside
the interface, how would that be different than in Abstract Class?

Variablen in Schnittstellen sind standardmäßig öffentlich statisch und endgültig. Die Frage könnte wie folgt lauten: Wenn alle Variablen in der abstrakten Klasse öffentlich sind? Nun, sie können im Gegensatz zu den Variablen in Schnittstellen immer noch nicht statisch und nicht endgültig sein.

Abschließend möchte ich noch einen Punkt zu den oben genannten hinzufügen: Abstrakte Klassen sind immer noch Klassen und fallen in einen einzelnen Vererbungsbaum, während Schnittstellen in Mehrfachvererbung vorhanden sein können.


13
  1. Schnittstelle:
    • Wir implementieren (oder definieren) keine Methoden, wir tun dies in abgeleiteten Klassen.
    • Wir deklarieren keine Mitgliedsvariablen in Schnittstellen.
    • Schnittstellen drücken die HAS-A-Beziehung aus. Das heißt, sie sind eine Maske von Objekten.
  2. Abstrakte Klasse:
    • Wir können Methoden in abstrakten Klassen deklarieren und definieren.
    • Wir verstecken Konstruktoren davon. Das heißt, es wird kein Objekt direkt daraus erstellt.
    • Die abstrakte Klasse kann Mitgliedsvariablen enthalten.
    • Abgeleitete Klassen erben an abstrakte Klassen, dh Objekte aus abgeleiteten Klassen werden nicht maskiert, sondern an abstrakte Klassen. Die Beziehung ist in diesem Fall IS-A.

Das ist meine Meinung.


12

Von CLR über C # von Jeffrey Richter kopiert ...

Ich höre oft die Frage: "Soll ich einen Basistyp oder eine Schnittstelle entwerfen?" Die Antwort ist nicht immer eindeutig.

Hier sind einige Richtlinien, die Ihnen helfen könnten:

■■ Beziehung zwischen IS-A und CAN-DO Ein Typ kann nur eine Implementierung erben. Wenn der abgeleitete Typ keine IS-A-Beziehung zum Basistyp beanspruchen kann, verwenden Sie keinen Basistyp. Verwenden Sie eine Schnittstelle. Schnittstellen implizieren eine CAN-DO-Beziehung. Wenn die CAN-DO-Funktionalität zu verschiedenen Objekttypen zu gehören scheint, verwenden Sie eine Schnittstelle. Beispielsweise kann ein Typ Instanzen von sich selbst in einen anderen Typ konvertieren (IConvertible), ein Typ kann eine Instanz von sich selbst serialisieren (ISerializable) usw. Beachten Sie, dass Werttypen von System.ValueType abgeleitet werden müssen und daher nicht abgeleitet werden können aus einer beliebigen Basisklasse. In diesem Fall müssen Sie eine CAN-DO-Beziehung verwenden und eine Schnittstelle definieren.

■■ Benutzerfreundlichkeit Für Sie als Entwickler ist es im Allgemeinen einfacher, einen neuen Typ zu definieren, der von einem Basistyp abgeleitet ist, als alle Methoden einer Schnittstelle zu implementieren. Der Basistyp kann viele Funktionen bereitstellen, sodass der abgeleitete Typ wahrscheinlich nur relativ kleine Änderungen an seinem Verhalten erfordert. Wenn Sie eine Schnittstelle angeben, muss der neue Typ alle Mitglieder implementieren.

■■ Konsistente Implementierung Unabhängig davon, wie gut ein Schnittstellenvertrag dokumentiert ist, ist es sehr unwahrscheinlich, dass jeder den Vertrag zu 100 Prozent korrekt implementiert. In der Tat leidet COM unter genau diesem Problem, weshalb einige COM-Objekte nur mit Microsoft Word oder Windows Internet Explorer ordnungsgemäß funktionieren. Indem Sie einen Basistyp mit einer guten Standardimplementierung bereitstellen, verwenden Sie zunächst einen Typ, der funktioniert und gut getestet ist. Sie können dann Teile ändern, die geändert werden müssen.

■■ Versionierung Wenn Sie dem Basistyp eine Methode hinzufügen, erbt der abgeleitete Typ die neue Methode, Sie verwenden zunächst einen funktionierenden Typ und der Quellcode des Benutzers muss nicht einmal neu kompiliert werden. Das Hinzufügen eines neuen Elements zu einer Schnittstelle zwingt den Erben der Schnittstelle, seinen Quellcode zu ändern und neu zu kompilieren.


1
@AbdullahShoaib ist ein und jeder kann, aber nicht kann, hier gibt es einen Unterschied. Dies ist der Grund, wir brauchen Schnittstelle. Can-Do-Verhalten wird ebenfalls Teil davon sein abstract class.
Überaustausch

10

Eine Schnittstelle definiert einen Vertrag für einen Dienst oder eine Reihe von Diensten. Sie bieten Polymorphismus auf horizontale Weise, indem zwei völlig unabhängige Klassen dieselbe Schnittstelle implementieren können, aber austauschbar als Parameter für den Typ der von ihnen implementierten Schnittstelle verwendet werden, da beide Klassen versprochen haben, die von der Schnittstelle definierten Dienste zu erfüllen. Schnittstellen enthalten keine Implementierungsdetails.

Eine abstrakte Klasse definiert eine Basisstruktur für ihre Unterklassen und optional eine teilweise Implementierung. Abstrakte Klassen bieten Polymorphismus in vertikaler, aber gerichteter Weise, indem jede Klasse, die die abstrakte Klasse erbt, als Instanz dieser abstrakten Klasse behandelt werden kann, aber nicht umgekehrt. Abstrakte Klassen können und enthalten häufig Implementierungsdetails, können jedoch nicht selbst instanziiert werden - nur ihre Unterklassen können "neu erstellt" werden.

C # ermöglicht wohlgemerkt auch die Vererbung von Schnittstellen.


1
Die Verwendung der Begriffe horizontal und vertikal machte es sehr deutlich, sich den Unterschied vorzustellen.
Unendlichkeit

10

Die meisten Antworten konzentrieren sich auf den technischen Unterschied zwischen abstrakter Klasse und Schnittstelle, aber da eine Schnittstelle technisch gesehen im Grunde eine Art abstrakte Klasse ist (eine ohne Daten oder Implementierung), denke ich, dass dies konzeptionell ist Unterschied weitaus interessanter ist, und das könnte sein Die Interviewer sind hinterher.

Eine Schnittstelle ist eine Vereinbarung . Darin heißt es: "So werden wir miteinander reden". Es kann keine Implementierung hat , weil es nicht hat sollte jede Implementierung haben. Es ist ein Vertrag. Es ist wie bei den .hHeader-Dateien in C.

Eine abstrakte Klasse ist eine unvollständige Implementierung . Eine Klasse kann eine Schnittstelle implementieren oder nicht, und eine abstrakte Klasse muss sie nicht vollständig implementieren. Eine abstrakte Klasse ohne Implementierung ist nutzlos, aber völlig legal.

Grundsätzlich geht es in jeder abstrakten oder nicht abstrakten Klasse darum, was sie ist , während es bei einer Schnittstelle darum geht, wie Sie sie verwenden . Zum Beispiel: Animalkönnte eine abstrakte Klasse sein, die einige grundlegende Stoffwechselfunktionen implementiert und abstrakte Methoden für Atmung und Fortbewegung spezifiziert, ohne eine Implementierung zu geben, da sie keine Ahnung hat, ob sie durch Kiemen oder Lungen atmen soll und ob sie fliegt, schwimmt, geht oder kriecht.MountAuf der anderen Seite könnte es sich um eine Schnittstelle handeln, die angibt, dass Sie das Tier reiten können, ohne zu wissen, um welche Art von Tier es sich handelt (oder ob es überhaupt ein Tier ist!).

Die Tatsache, dass eine Schnittstelle hinter den Kulissen im Grunde eine abstrakte Klasse mit nur abstrakten Methoden ist, spielt keine Rolle. Konzeptionell erfüllen sie völlig unterschiedliche Rollen.


10

Da Sie vielleicht das theoretische Wissen von den Experten erhalten haben, verbringe ich nicht viele Worte damit, all diese hier zu wiederholen, sondern lassen Sie mich anhand eines einfachen Beispiels erklären, wo wir und verwenden können Interfaceund was nicht Abstract class.

Stellen Sie sich vor, Sie entwerfen eine Anwendung, um alle Funktionen von Autos aufzulisten. In verschiedenen Punkten benötigen Sie eine gemeinsame Vererbung, da einige der Eigenschaften wie DigitalFuelMeter, Klimaanlage, Sitzverstellung usw. für alle Fahrzeuge gleich sind. Ebenso benötigen wir nur für einige Klassen eine Vererbung, da einige der Eigenschaften wie das Bremssystem (ABS, EBD) nur für einige Autos gelten.

Die folgende Klasse dient als Basisklasse für alle Autos:

public class Cars
{
    public string DigitalFuelMeter()
    {
        return "I have DigitalFuelMeter";
    }

    public string AirCondition()
    {
        return "I have AC";
    }

    public string SeatAdjust()
    {
        return "I can Adjust seat";
    }
}

Bedenken Sie, dass wir für jedes Auto eine eigene Klasse haben.

public class Alto : Cars
{
    // Have all the features of Car class    
}

public class Verna : Cars
{
    // Have all the features of Car class + Car need to inherit ABS as the Braking technology feature which is not in Cars        
}

public class Cruze : Cars
{
    // Have all the features of Car class + Car need to inherit EBD as the Braking technology feature which is not in Cars        
}

Bedenken Sie, dass wir eine Methode zur Vererbung der Bremstechnologie für die Autos Verna und Cruze benötigen (gilt nicht für Alto). Obwohl beide die Bremstechnologie verwenden, ist die "Technologie" unterschiedlich. Wir erstellen also eine abstrakte Klasse, in der die Methode als abstrakt deklariert wird und in ihren untergeordneten Klassen implementiert werden sollte.

public abstract class Brake
{
    public abstract string GetBrakeTechnology();
}

Jetzt versuchen wir, von dieser abstrakten Klasse zu erben, und die Art des Bremssystems ist in Verna und Cruze implementiert:

public class Verna : Cars,Brake
{
    public override string GetBrakeTechnology()
    {
        return "I use ABS system for braking";
    }       
}

public class Cruze : Cars,Brake
{
    public override string GetBrakeTechnology()
    {
       return "I use EBD system for braking";
    }         
}

Sehen Sie das Problem in den beiden oben genannten Klassen? Sie erben von mehreren Klassen, die C # .Net nicht zulässt, obwohl die Methode in den untergeordneten Klassen implementiert ist. Hier kommt die Notwendigkeit der Schnittstelle.

interface IBrakeTechnology
{
    string GetBrakeTechnology();
}

Und die Implementierung ist unten angegeben:

public class Verna : Cars, IBrakeTechnology
{
    public string GetBrakeTechnology()
    {
        return "I use ABS system for braking";
    }
}

public class Cruze : Cars, IBrakeTechnology
{
   public string GetBrakeTechnology()
   {
       return "I use EBD system for braking";
   }        
}

Jetzt können Verna und Cruze mit Hilfe von Interface mit ihrer eigenen Art von Bremstechnologien eine Mehrfachvererbung erreichen.


4
Dies ist aufgrund der Beispiele eine der besten Erklärungen.
Adam Mendoza

2
Das macht für mich Sinn, ohne das Gehirn zu zerbrechen. Ich habe nur versucht, ein Autobeispiel für meine Schüler zu finden. Vielen Dank, dass Sie sich die Zeit genommen haben, dies zusammenzustellen.
Tazboy

9

Schnittstellen sind eine leichte Möglichkeit, ein bestimmtes Verhalten durchzusetzen. Das ist eine Art zu denken.


8

Diese Antworten sind allzu lang.

  • Schnittstellen dienen zum Definieren von Verhaltensweisen.

  • Abstrakte Klassen dienen dazu, ein Ding selbst zu definieren, einschließlich seines Verhaltens. Aus diesem Grund erstellen wir manchmal eine abstrakte Klasse mit einigen zusätzlichen Eigenschaften, die eine Schnittstelle erben.

Dies erklärt auch, warum Java nur die Einzelvererbung für Klassen unterstützt, die Schnittstellen jedoch nicht einschränkt. Weil ein konkretes Objekt nicht verschiedene Dinge sein kann, aber es kann verschiedene Verhaltensweisen haben.


7

1) Eine Schnittstelle kann als reine abstrakte Klasse angesehen werden, ist dieselbe, aber trotzdem nicht dieselbe, um eine Schnittstelle zu implementieren und von einer abstrakten Klasse zu erben. Wenn Sie von dieser reinen abstrakten Klasse erben, definieren Sie eine Hierarchie -> Vererbung, wenn Sie die Schnittstelle implementieren, die Sie nicht sind, und Sie können so viele Schnittstellen implementieren, wie Sie möchten, aber Sie können nur von einer Klasse erben.

2) Sie können eine Eigenschaft in einer Schnittstelle definieren, daher muss die Klasse, die diese Schnittstelle implementiert, diese Eigenschaft haben.

Zum Beispiel:

  public interface IVariable
  {
      string name {get; set;}
  }

Die Klasse, die diese Schnittstelle implementiert, muss eine solche Eigenschaft haben.


7

Obwohl diese Frage ziemlich alt ist, möchte ich noch einen weiteren Punkt zugunsten von Schnittstellen hinzufügen:

Schnittstellen können mit beliebigen Tools für die Abhängigkeitsinjektion injiziert werden, wobei die Injektion als abstrakte Klasse nur von sehr wenigen unterstützt wird.


1
Ich glaube, Sie meinen, dass ein DI-Tool eine Klasse einfügen kann, die eine Schnittstelle implementiert. Einige dieser Tools können auch Klassen einfügen, die von einer abstrakten Klasse abgeleitet sind, oder sagen Sie, dass dies unmöglich ist?
John Saunders

6

Aus einer anderen Antwort von mir geht es hauptsächlich darum, wann man eins gegen das andere verwendet:

Nach meiner Erfahrung werden Schnittstellen am besten verwendet, wenn Sie mehrere Klassen haben, die jeweils auf dieselbe Methode oder dieselben Methoden reagieren müssen, damit sie austauschbar von anderem Code verwendet werden können, der für die gemeinsame Schnittstelle dieser Klassen geschrieben wird. Die beste Verwendung einer Schnittstelle ist, wenn das Protokoll wichtig ist, die zugrunde liegende Logik jedoch für jede Klasse unterschiedlich sein kann. Wenn Sie sonst Logik duplizieren würden, ziehen Sie stattdessen abstrakte Klassen oder Standardklassenvererbung in Betracht.


6

Schnittstellentypen vs. abstrakte Basisklassen

Angepasst an Pro C # 5.0 und das .NET 4.5 Framework- Buch.

Der Schnittstellentyp scheint einer abstrakten Basisklasse sehr ähnlich zu sein. Denken Sie daran, dass eine Klasse, die als abstrakt markiert ist, eine beliebige Anzahl von abstrakten Elementen definieren kann, um eine polymorphe Schnittstelle für alle abgeleiteten Typen bereitzustellen. Selbst wenn eine Klasse eine Reihe von abstrakten Elementen definiert, ist es auch frei, eine beliebige Anzahl von Konstruktoren, Felddaten, nicht abstrakten Elementen (mit Implementierung) usw. zu definieren. Schnittstellen enthalten dagegen nur abstrakte Elementdefinitionen. Die von einer abstrakten übergeordneten Klasse eingerichtete polymorphe Schnittstelle weist eine wesentliche Einschränkung auf, da nur abgeleitete Typen die vom abstrakten übergeordneten Element definierten Elemente unterstützen. In größeren Softwaresystemen ist es jedoch sehr üblich, mehrere Klassenhierarchien zu entwickeln, die über System.Object hinaus kein gemeinsames übergeordnetes Element haben. Da abstrakte Elemente in einer abstrakten Basisklasse nur für abgeleitete Typen gelten, können wir keine Typen in verschiedenen Hierarchien konfigurieren, um dieselbe polymorphe Schnittstelle zu unterstützen. Angenommen, Sie haben die folgende abstrakte Klasse definiert:

public abstract class CloneableType
{
// Only derived types can support this
// "polymorphic interface." Classes in other
// hierarchies have no access to this abstract
// member.
   public abstract object Clone();
}

Aufgrund dieser Definition können nur Mitglieder, die CloneableType erweitern, die Clone () -Methode unterstützen. Wenn Sie eine neue Gruppe von Klassen erstellen, die diese Basisklasse nicht erweitern, können Sie diese polymorphe Schnittstelle nicht erhalten. Sie können sich auch daran erinnern, dass C # keine Mehrfachvererbung für Klassen unterstützt. Wenn Sie also einen MiniVan erstellen möchten, der ein Auto und ein klonbarer Typ ist, können Sie dies nicht tun:

// Nope! Multiple inheritance is not possible in C#
// for classes.
public class MiniVan : Car, CloneableType
{
}

Wie Sie sich vorstellen können, helfen Schnittstellentypen. Nachdem eine Schnittstelle definiert wurde, kann sie von jeder Klasse oder Struktur, in jeder Hierarchie, in jedem Namespace oder jeder Assembly (geschrieben in einer beliebigen .NET-Programmiersprache) implementiert werden. Wie Sie sehen können, sind Schnittstellen stark polymorph. Betrachten Sie die Standard-.NET-Schnittstelle mit dem Namen ICloneable, die im System-Namespace definiert ist. Diese Schnittstelle definiert eine einzelne Methode namens Clone ():

public interface ICloneable
{
object Clone();
}

6

Antwort auf die zweite Frage: Die in publicdefinierte Variable interfaceist static finalstandardmäßig, während die publicVariable in der abstractKlasse eine Instanzvariable ist.


6

Natürlich ist es wichtig, das Verhalten der Schnittstelle und der abstrakten Klasse in OOP zu verstehen (und wie Sprachen damit umgehen), aber ich denke, es ist auch wichtig zu verstehen, was genau jeder Begriff bedeutet. Können Sie sich vorstellen, dass der ifBefehl nicht genau der Bedeutung des Begriffs entspricht? Tatsächlich reduzieren einige Sprachen sogar noch mehr die Unterschiede zwischen einer Schnittstelle und einer Zusammenfassung. Wenn die beiden Begriffe eines Tages zufällig fast identisch funktionieren, können Sie zumindest selbst definieren, wo (und warum) einer von ihnen sein soll benutzt für.

Wenn Sie einige Wörterbücher und andere Schriftarten durchlesen, finden Sie möglicherweise unterschiedliche Bedeutungen für denselben Begriff, haben jedoch einige gemeinsame Definitionen. Ich denke, diese beiden Bedeutungen, die ich auf dieser Seite gefunden habe, sind wirklich sehr, sehr gut und geeignet.

Schnittstelle:

Eine Sache oder ein Umstand, der es separaten und manchmal inkompatiblen Elementen ermöglicht, effektiv zu koordinieren.

Abstrakt:

Etwas, das an sich die wesentlichen Eigenschaften von etwas Umfangreicherem oder Allgemeinerem oder von mehreren Dingen konzentriert; Wesen.

Beispiel:

Sie haben ein Auto gekauft und es braucht Kraftstoff.

Geben Sie hier die Bildbeschreibung ein

Ihr Automodell ist ein XYZGenre ABC, also ein konkretes Auto, eine bestimmte Instanz eines Autos. Ein Auto ist kein echtes Objekt. Tatsächlich ist es eine abstrakte Reihe von Standards (Qualitäten), um ein bestimmtes Objekt zu erstellen. Kurz gesagt, Auto ist eine abstrakte Klasse , es ist "etwas, das in sich die wesentlichen Eigenschaften von etwas Umfangreicherem oder Allgemeinerem konzentriert" .

Der einzige Kraftstoff, der der manuellen Spezifikation des Fahrzeugs entspricht, sollte zum Auffüllen des Fahrzeugtanks verwendet werden. In der Realität gibt es nichts, was Sie daran hindert, Kraftstoff nachzufüllen, aber der Motor funktioniert nur mit dem angegebenen Kraftstoff ordnungsgemäß. Daher ist es besser, die Anforderungen zu erfüllen. Die Anforderungen besagen, dass es wie andere Autos des gleichen Genres akzeptiertABC einen Standard-Kraftstoffsatz .

In einer objektorientierten Ansicht sollte Kraftstoff für das Genre ABCnicht als Klasse deklariert werden, da es keinen konkreten Kraftstoff für ein bestimmtes Genre des Autos gibt. Obwohl Ihr Auto eine abstrakte Klasse Kraftstoff oder Fahrzeugkraftstoff akzeptieren könnte, müssen Sie sich daran erinnern, dass nur ein Teil des vorhandenen Fahrzeugkraftstoffs der Spezifikation entspricht, die die Anforderungen in Ihrem Autohandbuch implementiert. Kurz gesagt, sie sollten die Schnittstelle implementieren ABCGenreFuel, die "... es ermöglicht, dass separate und manchmal inkompatible Elemente effektiv koordiniert werden" .

Nachtrag

Darüber hinaus sollten Sie die Bedeutung des Begriffs Klasse berücksichtigen, der (von derselben zuvor erwähnten Site) lautet:

Klasse:

Eine Anzahl von Personen oder Dingen, die aufgrund gemeinsamer Attribute, Eigenschaften, Qualitäten oder Merkmale als eine Gruppe bildend angesehen werden; nett;

Auf diese Weise sollte eine Klasse (oder abstrakte Klasse) nicht nur gemeinsame Attribute (wie eine Schnittstelle) darstellen, sondern eine Art Gruppe mit gemeinsamen Attributen. Eine Schnittstelle muss keine Art darstellen. Es muss gemeinsame Attribute darstellen. Auf diese Weise denke ich, dass Klassen und abstrakte Klassen verwendet werden können, um Dinge darzustellen, die ihre Aspekte nicht oft ändern sollten, wie ein Mensch ein Säugetier, weil es einige Arten darstellt. Arten sollten sich nicht so oft ändern.


1
zu viel Flusen, lassen Sie es für die Leute nicht verwirrender klingen, als es vielleicht schon ist.
Ganjeii

5

Aus Codierungsperspektive

Eine Schnittstelle kann eine abstrakte Klasse ersetzen, wenn die abstrakte Klasse nur abstrakte Methoden enthält. Andernfalls bedeutet das Ändern der Abstract-Klasse in eine Schnittstelle, dass Sie die von Inheritance bereitgestellte Wiederverwendbarkeit von Code verlieren.

Aus gestalterischer Sicht

Behalten Sie es als abstrakte Klasse bei, wenn es sich um eine "Ist eine" Beziehung handelt und Sie eine Teilmenge oder alle Funktionen benötigen. Behalten Sie es als Schnittstelle bei, wenn es sich um eine "Sollte" -Beziehung handelt.

Entscheiden Sie, was Sie benötigen: nur die Durchsetzung der Richtlinien oder die Wiederverwendbarkeit des Codes UND die Richtlinie.


3

Einige andere Unterschiede:

Abstrakte Klassen können statische Methoden, Eigenschaften, Felder usw. und Operatoren haben, Schnittstellen nicht. Der Cast-Operator erlaubt das Casting zu / von der abstrakten Klasse, aber nicht das Casting zur / von der Schnittstelle.

Sie können die abstrakte Klasse so gut wie alleine verwenden, auch wenn sie niemals implementiert ist (über ihre statischen Elemente) und Sie können die Schnittstelle in keiner Weise alleine verwenden.


In Java kann die Schnittstelle eine Mitgliedsvariable haben, aber standardmäßig werden sie öffentlich statisch. Die Schnittstelle kann statische Felder haben
Jitendra Vispute

Ja, die Schnittstelle kann statische Felder haben. ABER Schnittstelle kann keine statischen Methoden haben.
ein Lernender
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.