Frage Schnittstelle vs abstrakte Klasse (allgemeine OO)


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, den ich mir vorstellen kann, 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 das folgende ist wahr. Wenn ich einen wichtigen Punkt vermisse, lass es mich 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 existieren. Eine Klasse kann mehrere Schnittstellen implementieren.

Abstrakte Klasse:

Nur abstrakte Methoden müssen von der Unterklasse implementiert werden. Eine Abstract-Klasse kann normale Methoden mit Implementierungen haben. Die abstrakte Klasse kann neben Ereignissen, Delegaten, Eigenschaften und Methoden auch Klassenvariablen haben. Eine Klasse kann nur eine abstrakte Klasse nur dann implementieren, wenn in C # keine Multi-Vererbung vorhanden ist.

  1. Nach all dem kam der Interviewer mit der Frage "Was wäre, wenn Sie eine Abstraktionsklasse mit nur abstrakten Methoden hätten? Wie würde das anders als eine Schnittstelle sein?" Ich kannte die Antwort nicht, aber ich denke, es ist das oben erwähnte Erbe, oder?

  2. Ein anderer Interviewer fragte mich, was wäre, wenn Sie eine öffentliche Variable in der Schnittstelle hätten, was wäre das anders als in der abstrakten Klasse? Ich bestand darauf, 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:


1197
2018-04-17 16:42


Ursprung


Antworten:


Während Ihre Frage darauf hinweist, dass es sich um "allgemeine OO" handelt, scheint es, als ob Sie sich auf die .NET-Verwendung dieser Begriffe konzentrieren.

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

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

Wie allgemeine OO-Begriffe, sind die Unterschiede nicht unbedingt gut definiert. Zum Beispiel gibt es C ++ - Programmierer, die ähnliche starre Definitionen haben können (Schnittstellen sind eine strikte Untergruppe von abstrakten Klassen, die keine Implementierung enthalten können), während einige sagen können, dass eine abstrakte Klasse mit einigen Standardimplementierungen immer noch eine Schnittstelle oder nicht abstrakt ist Die Klasse kann weiterhin eine Schnittstelle definieren.

Tatsächlich gibt es ein C ++ - Idiom namens "Non-Virtual Interface" (NVI), bei dem es sich bei den öffentlichen Methoden um nicht virtuelle Methoden handelt, die auf private virtuelle Methoden zugreifen:


632
2018-04-17 17:18



Wie wäre es mit einer Analogie: Als ich in der Air Force war, ging ich zum Pilotentraining und wurde ein Pilot der USAF (US Air Force). Zu diesem Zeitpunkt war ich nicht qualifiziert, um etwas zu fliegen, und musste am Flugzeugtyptraining teilnehmen. Sobald ich mich qualifiziert hatte, war ich Pilot (Abstract-Klasse) und Pilot C-141 (konkrete Klasse). Bei einer meiner Aufgaben erhielt ich eine zusätzliche Aufgabe: Sicherheitsbeauftragter. Jetzt war ich noch Pilot und C-141-Pilot, aber ich erfüllte auch die Aufgaben des Sicherheitsbeauftragten (ich habe sozusagen den 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 einhalten, und alle C-141 (oder F-16 oder T-38) Piloten sind "USAF-Piloten". Jeder kann ein Sicherheitsbeauftragter sein. Also, um zusammenzufassen:

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

Anmerkung: Dies sollte eine Analogie sein, um das Konzept zu erklären, nicht eine Kodierungsempfehlung. Siehe die verschiedenen Kommentare unten, die Diskussion ist interessant.


754
2017-08-30 04:40



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

Die abstrakte Klassenvererbung wird verwendet, wenn die abgeleitete Klasse die Kerneigenschaften und das Verhalten der abstrakten Klasse teilt. Die Art von Verhalten, die die Klasse tatsächlich definiert.

Andererseits wird die Schnittstellenvererbung verwendet, wenn die Klassen das periphere Verhalten teilen, also diejenigen, die nicht notwendigerweise die abgeleitete Klasse definieren.

Für z. Ein Auto und ein Truck teilen viele Kerneigenschaften und das Verhalten einer abstrakten Klasse von Automobilen, aber sie teilen auch etwas peripheres Verhalten wie Abgas erzeugen, das selbst nicht-automobile Klassen wie Drillers oder PowerGeneratoren teilen und nicht notwendigerweise ein Auto oder einen LKW definieren , so können Auto, LKW, Driller und PowerGenerator die gleiche Schnittstelle IExhaust teilen.


194
2017-08-31 12:09



Kurz: Abstrakte Klassen werden verwendet für Modellieren eine Klassenhierarchie ähnlich aussehender Klassen (zB Animal kann eine abstrakte Klasse sein und Human, Lion, Tiger können konkrete abgeleitete Klassen sein)

UND

Schnittstelle wird für verwendet Kommunikation zwischen 2 ähnlichen / nicht ähnlichen Klassen, die sich nicht um den Typ der implementierenden Schnittstelle kümmern (zB Height kann Interface-Eigenschaft sein und kann von Mensch, Gebäude, Baum implementiert werden. Es ist egal, ob du essen kannst, du kannst schwimmen kann sterben oder irgendetwas .. es zählt nur eine Sache, die Sie brauchen Höhe (Implementierung in Ihrer Klasse)).


163
2018-04-05 09:53



Es gibt ein paar andere Unterschiede -

Schnittstellen können keine konkreten Implementierungen haben. Abstrakte Basisklassen können. Dadurch können Sie dort konkrete Implementierungen bereitstellen. Dies kann einer abstrakten Basisklasse ermöglichen, einen strengeren Vertrag zu liefern, während eine Schnittstelle wirklich nur beschreibt, wie eine Klasse verwendet wird. (Die abstrakte Basisklasse kann nicht virtuelle Member haben, die das Verhalten definieren, wodurch dem Basisklassenautor mehr Kontrolle gegeben wird.)

Mehr als eine Schnittstelle kann in einer Klasse implementiert werden. Eine Klasse kann nur von einer einzelnen abstrakten Basisklasse abgeleitet werden. Dies ermöglicht eine polymorphe Hierarchie unter Verwendung von Schnittstellen, jedoch nicht von abstrakten Basisklassen. Dies ermöglicht auch eine Pseudo-Mehrfachvererbung unter Verwendung von Schnittstellen.

Abstrakte Basisklassen können in v2 + geändert werden, ohne die API zu unterbrechen. Änderungen an den Schnittstellen brechen die Änderungen.

[C # /. NET-spezifische] 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.


74
2018-04-17 16:46



Erbe
Betrachten Sie ein Auto und einen Bus. Sie sind zwei verschiedene Fahrzeuge. Dennoch haben sie einige gemeinsame Eigenschaften wie eine 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 Erbe. Wir verwenden sie, um Objekte in einfachere Basisformen und ihre Kinder zu klassifizieren, wie wir oben gesehen haben.

Abstrakte Klassen

Abstrakte Klassen sind unvollständig Objekte. Um es weiter zu verstehen, betrachten wir die Fahrzeuganalogie noch einmal.
Ein Fahrzeug kann gefahren werden. Recht? Aber verschiedene Fahrzeuge werden auf unterschiedliche Art und Weise angetrieben ... Zum Beispiel können Sie kein Auto fahren, genauso wie Sie ein Fahrrad fahren.
Wie kann man die Fahrfunktion eines Fahrzeugs darstellen? Es ist schwieriger zu prüfen, um welche Art von Fahrzeug es sich handelt, und es mit seiner eigenen Funktion zu fahren; Sie müssten beim Hinzufügen eines neuen Fahrzeugtyps die Klasse Fahrer immer wieder wechseln.
Hier kommt die Rolle der abstrakten Klassen und Methoden. Sie können die Laufwerksmethode als abstrakt definieren, um zu bestimmen, dass alle erbenden Kinder 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 ein Fehler wird ausgegeben.
Kurz gesagt .. eine abstrakte Klasse ist eine teilweise unvollständige Klasse mit einigen unvollständigen Funktionen, die die erbenden Kinder ihre eigenen angeben müssen.

Schnittstellen Schnittstellen sind völlig unvollständig. Sie haben keine Eigenschaften. Sie zeigen nur an, dass die ererbenden Kinder in der Lage sind, etwas zu tun ...
Angenommen, Sie haben verschiedene Arten von Mobiltelefonen mit Ihnen. Jeder von ihnen hat verschiedene Möglichkeiten, verschiedene Funktionen zu erfüllen; Bsp: rufe eine Person an. Der Hersteller des Telefons legt fest, wie es gemacht wird. Hier können die Mobiltelefone eine Nummer wählen, dh sie können wählen. Stellen wir das als Schnittstelle dar.

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

Hier definiert der Hersteller von Dialable, wie eine Nummer gewählt wird. Sie müssen ihm nur eine Nummer geben, um zu wählen.

// 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);
}
.....

Dadurch, dass Schnittstellen anstelle von abstrakten Klassen verwendet werden, muss der Schreiber der Funktion, die ein Dialable verwendet, sich nicht um seine Eigenschaften kümmern. Bsp .: Hat es einen Touchscreen oder ein Wähltastenfeld? Ist es ein Festnetztelefon oder ein Mobiltelefon? Sie müssen nur wissen, ob es wählbar ist; Erbt (oder implementiert) er die Dialable-Schnittstelle.

Und noch wichtigerWenn du eines Tages das Dialable mit einem anderen auswählst

......
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ählwort verwendet, nicht von anderen als den in der Wählbaren Schnittstelle angegebenen Details abhängt. Sie implementieren beide eine Dialable-Schnittstelle und das ist das einzige, was die Funktion interessiert.

Schnittstellen werden häufig von Entwicklern verwendet, um die Interoperabilität (Verwendung synonym) zwischen Objekten sicherzustellen, sofern sie eine gemeinsame Funktion haben (so wie Sie zum 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 beliebig viele Schnittstellen implementieren (vererben) können, aber nur eine einzelne Elternklasse erweitern (erben) dürfen.

Mehr Info Abstrakte Klassen vs Schnittstellen 


63
2018-06-14 13:11



Wenn Sie darüber nachdenken java als OOP-Sprache, um diese Frage zu beantworten, verursacht Java 8 Release einige der Inhalte in den obigen Antworten als obsolet. Jetzt kann Java-Schnittstelle Standardmethoden mit konkreter Implementierung haben.

Orakel Webseite bietet wichtige Unterschiede zwischen interface und abstract Klasse.

Erwägen Sie die Verwendung abstrakter Klassen ob :

  1. Sie möchten Code zwischen mehreren eng verwandten Klassen freigeben.
  2. Sie erwarten, dass Klassen, die Ihre abstrakte Klasse erweitern, viele gebräuchliche Methoden oder Felder aufweisen oder Zugriffsmodifizierer erfordern, die nicht öffentlich sind (z. B. "geschützt" und "privat").
  3. Sie möchten nicht statische oder nicht endgültige Felder deklarieren.

Erwägen Sie die Verwendung von Schnittstellen ob :

  1. Sie erwarten, dass nicht verwandte Klassen Ihre Schnittstelle implementieren. Zum Beispiel können viele nicht verwandte Objekte implementiert werden Serializable Schnittstelle.
  2. Sie möchten das Verhalten eines bestimmten Datentyps angeben, aber nicht darauf achten, wer sein Verhalten implementiert.
  3. Sie möchten die mehrfache Vererbung von Typ ausnutzen.

In einfachen Worten würde ich gerne verwenden

Schnittstelle: Um einen Vertrag durch mehrere nicht verwandte Objekte zu implementieren

abstrakte Klasse: Um das gleiche oder ein anderes Verhalten zwischen mehreren verwandten Objekten zu implementieren

Sehen 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
2017-11-27 19:20



Die Interviewer bellen einen merkwürdigen Baum auf. Für Sprachen wie C # und Java gibt es einen Unterschied, aber in anderen Sprachen wie C ++ gibt es keinen Unterschied. OO-Theorie unterscheidet nicht die beiden, nur die Syntax der Sprache.

Eine abstrakte Klasse ist eine Klasse mit sowohl Implementierung als auch Schnittstelle (reine virtuelle Methoden), die vererbt wird. Schnittstellen haben in der Regel keine Implementierung, sondern nur reine virtuelle Funktionen.

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


30
2018-04-17 16:48



Durch die Implementierung von Interfaces erreichen Sie Komposition ("hat-a" -Beziehungen) statt Vererbung ("ist-a" -Beziehungen). Dies ist ein wichtiger Grundsatz, den Sie beachten sollten, wenn es um Entwurfsmuster geht, bei denen Sie Schnittstellen verwenden müssen, um eine Zusammensetzung von Verhaltensweisen anstelle einer Vererbung zu erreichen.


29
2018-04-17 16:52



Ich werde Tiefe Details der Schnittstelle und abstrakte Klasse erklären. Wenn Sie Überblick über Schnittstelle und abstrakte Klasse wissen, dann kommen die erste Frage in Ihren Geist, wenn wir die Schnittstelle verwenden sollten und wann wir die abstrakte Klasse verwenden sollten. Also bitte unten die Erklärung der Interface- und Abstract-Klasse.

  1. Wann sollten wir Interface benutzen?

    Wenn Sie nicht über die Implementierung wissen, haben wir nur eine Anforderungsspezifikation, dann gehen wir mit Interface 

  2. Wann sollten wir die abstrakte Klasse verwenden?

    Wenn Sie Implementierung aber nicht vollständig (teilweise Implementierung) kennen, dann gehen wir mit Abstraktionsklasse. 

    Schnittstelle

    Jede Methode standardmäßig public abstract bedeutet Schnittstelle ist 100% rein abstrakt.

    Abstrakt

    kann Konkrete Methode und Abstrakte Methode haben, was Konkrete Methode ist, welche Implementierung in der Klasse Abstraktion hat,    Eine abstrakte Klasse ist eine Klasse, die als abstrakt deklariert ist - sie kann abstrakte Methoden enthalten oder auch nicht.

    Schnittstelle

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

    Q. Warum deklarieren wir Interface nicht als privat und geschützt?

    Weil die Interface-Methode standardmäßig public abstract ist, so dass wir die Schnittstelle nicht als privat und geschützt deklarieren.

    Schnittstellenmethode
       Auch können wir die Schnittstelle nicht als privat, geschützt, final, statisch, synchronisiert, nativ deklarieren .....

    Ich werde den Grund angeben:  warum wir keine synchronisierte Methode deklarieren, weil wir kein Objekt der Schnittstelle erstellen können und die Arbeit an einem Objekt synchronisieren, so dass wir die synchronisierte Methode nicht deklarieren  Transiente Konzepte sind auch nicht anwendbar, da transiente Arbeit mit synchronisiert ist.

    Abstrakt 

    wir sind gerne mit öffentlichen, privaten final static .... bedeutet keine Beschränkung sind in abstract.

    Schnittstelle

    Variablen werden in Interface standardmäßig als statisches finales deklariert, so dass wir auch nicht als privat, geschützt deklariert sind.

    Der flüchtige Modifikator ist in der Schnittstelle auch nicht anwendbar, da die Schnittstellenvariable standardmäßig statisch ist. Final und final. Sie können den Wert nicht mehr ändern, nachdem er den Wert in die Variable eingegeben hat. Sobald Sie die Variable in der Schnittstelle deklariert haben, müssen Sie die Variable zuweisen.

    Und volatile Variable ist Änderungen beibehalten, so ist es opp. Um das zu beenden, verwenden wir keine flüchtige Variable in der Schnittstelle.

    Abstrakt

    Abstrakte Variable muss nicht öffentlich statisch final deklariert werden.

Ich hoffe, dieser Artikel ist nützlich.


23
2018-05-31 06:33



Für .Net,

Ihre Antwort auf den zweiten Interviewer ist auch die Antwort auf den ersten ... Abstrakte Klassen können Implementierung haben, UND Zustand, Schnittstellen können nicht ...

EDIT: Bei einer anderen Anmerkung würde ich nicht einmal die Phrase 'subclass' (oder die '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 so definiert wurde, dass sie diese Schnittstelle "implementiert". Es erbt nichts ... Du musst alles explizit hinzufügen.


21
2018-04-17 16:48