1573 Stimmen

Schnittstelle vs. abstrakte Klasse (allgemeine OO)

Ich hatte kürzlich zwei Telefoninterviews, in denen ich nach den Unterschieden zwischen einer Schnittstelle und einer abstrakten Klasse gefragt wurde. Ich habe jeden Aspekt erklärt, der mir einfiel, aber es scheint, dass sie darauf warten, dass ich etwas Bestimmtes erwähne, und ich weiß nicht, was es ist.

Aus meiner Erfahrung heraus denke ich, dass das Folgende zutrifft. Sollte ich einen wichtigen Punkt übersehen haben, lassen Sie es mich bitte wissen.

Schnittstelle:

Jede einzelne Methode, die in einer Schnittstelle deklariert ist, muss in der Unterklasse implementiert werden. Nur Ereignisse, Delegaten, Eigenschaften (C#) und Methoden können in einer Schnittstelle vorhanden sein. Eine Klasse kann mehrere Interfaces implementieren.

Abstrakte Klasse:

Nur die abstrakten Methoden müssen von der Unterklasse implementiert werden. Eine abstrakte Klasse kann normale Methoden mit Implementierungen haben. Eine abstrakte Klasse kann neben Ereignissen, Delegaten, Eigenschaften und Methoden auch Klassenvariablen haben. Eine Klasse kann nur eine abstrakte Klasse implementieren, da es in C# keine Multi-Vererbung gibt.

  1. Nach all dem kam der Interviewer mit der 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 die Vererbung, wie oben erwähnt, oder?

  2. Ein anderer Interviewer fragte mich, was wäre, wenn man eine öffentliche Variable innerhalb der Schnittstelle hätte, inwiefern wäre das anders als bei einer abstrakten Klasse? Ich bestand darauf, dass man keine öffentliche Variable innerhalb einer Schnittstelle haben kann. Ich wusste nicht, was er hören wollte, aber er war auch nicht zufrieden.

Siehe auch :

461 Stimmen

Obwohl ich es für wichtig halte, den Unterschied zwischen den beiden zu kennen, ist dies meiner Meinung nach keine gute Frage für ein Vorstellungsgespräch. Es sei denn, die Aufgabe bestand darin, ein Buch über OO-Themen zu schreiben. Es ist besser, wenn Sie nicht für diese Fledermäuse arbeiten.

117 Stimmen

@Alan: Ich mag das als Interviewfrage, aber ich würde niemanden auf diese Weise damit jagen - ich würde es wahrscheinlich eher so formulieren: "Wo würden Sie eine Schnittstelle einer abstrakten Basisklasse vorziehen, wenn Sie eine Hierarchie definieren?

12 Stimmen

Vielleicht wollten sie eine Antwort, die sich mehr auf das Design konzentriert... obwohl ich sie wie Sie als technische Frage behandelt hätte.

820voto

Michael Burr Punkte 320591

Während Ihre Frage angibt, dass sie für "allgemeine OO" ist, scheint sie sich wirklich auf die Verwendung dieser Begriffe in .NET zu konzentrieren.

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

  • Schnittstellen können keinen Zustand oder keine Implementierung haben
  • eine Klasse, die eine Schnittstelle implementiert, muss eine Implementierung aller Methoden dieser Schnittstelle bereitstellen
  • abstrakte Klassen können Zustand (Datenelemente) und/oder 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 werden, abstrakte Klassen nicht (dies ist wahrscheinlich der wichtigste konkrete Grund dafür, dass Schnittstellen getrennt von abstrakten Klassen existieren - sie ermöglichen eine Implementierung der Mehrfachvererbung, die viele der Probleme der allgemeinen MI beseitigt).

Als allgemeine OO-Begriffe sind die Unterschiede nicht unbedingt klar definiert. So gibt es z. B. C++-Programmierer, die ähnliche starre Definitionen vertreten (Schnittstellen sind eine strenge Teilmenge abstrakter Klassen, die keine Implementierung enthalten können), während andere sagen, dass eine abstrakte Klasse mit einigen Standardimplementierungen immer noch eine Schnittstelle ist oder dass eine nicht-abstrakte Klasse trotzdem eine Schnittstelle definieren kann.

In der Tat gibt es in C++ ein Idiom, das Non-Virtual Interface (NVI) genannt wird und bei dem die öffentlichen Methoden nicht-virtuelle Methoden sind, die auf private virtuelle Methoden "verweisen":

7 Stimmen

Ich danke Ihnen. Ich denke, da Ihre Antwort den Zustand und einen guten Überblick über alles andere erwähnt, markiere ich Ihre Antwort als endgültige Antwort. Sie haben recht, dass ich nach allgemeinem OO gefragt habe, da mein erster Interviewer nach allgemeinem OO gefragt hat, aber da ich ein C#-Typ bin, vergesse ich das gerne ;-) Auch danke für die C++ Erklärung, wie immer ist C++ umwerfend.

7 Stimmen

Ich denke, ein wichtiger Punkt in der von Michael gegebenen Erklärung ist, dass man bei der Implementierung einer Schnittstelle alle Mitglieder der Schnittstelle implementieren MUSS, aber bei der Vererbung von einer abstrakten Klasse ist es für eine Kindklasse NICHT ERFORDERLICH, die Mitglieder der Elternklasse zu implementieren

93 Stimmen

+1: Ich würde wetten, dass die Affen, die das Interview führen, nicht einmal wissen, dass andere Sprachen OO anders implementieren.

251voto

Prasun Punkte 2351

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

Die Vererbung von abstrakten Klassen wird verwendet, wenn die abgeleitete Klasse die Kerneigenschaften und das Verhalten der abstrakten Klasse teilt. Die Art des Verhaltens, die die Klasse tatsächlich definiert.

Andererseits wird die Schnittstellenvererbung verwendet, wenn die Klassen peripheres Verhalten teilen, das die abgeleitete Klasse nicht unbedingt definiert.

Ein Auto und ein Lastwagen teilen sich z.B. viele Kerneigenschaften und Verhaltensweisen einer abstrakten Klasse Automobile, aber sie teilen sich auch einige periphere Verhaltensweisen wie z.B. Auspuff erzeugen, die auch Nicht-Automobil-Klassen wie Bohrer oder Stromerzeuger teilen und nicht unbedingt ein Auto oder einen Lastwagen definieren, so dass Auto, Lastwagen, Bohrer und Stromerzeuger alle die gleiche Schnittstelle IExhaust teilen können.

40 Stimmen

Ich denke, eine noch bessere Analogie wäre "usesFuel", die die Vertrag Art der Schnittstelle.

0 Stimmen

@Pureferret wenn accelerate Teil des Kernverhaltens der abstrakten Klasse Automobile ist, kann ich dann nicht sagen accelerate zeigt die Vertrag natur. was ist vertragsnatur? warum dieses wort contract eingeführt, wenn wir über interface ?

0 Stimmen

@overexchange, denn die Schnittstelle ist in der Regel nur wo sich zwei "Flächen" treffen, aber das Wort "Vertrag" impliziert, dass es eine Vereinbarung über wie die beiden "Oberflächen" treffen aufeinander. Es ergibt keinen Sinn (zumindest für mich), dass die Erzeugung von Abgasen etwas ist, worüber man sich "einig" ist. Aber es macht Sinn (wiederum für mich), dass man sich darauf einigen kann, dass man Treibstoff verwenden muss.

242voto

Dhananjay Punkte 3515

Kurz: Abstrakte Klassen werden verwendet für Modellierung eine Klassenhierarchie von ähnlich aussehenden Klassen (z. B. kann Tier eine abstrakte Klasse sein und Mensch, Löwe, Tiger können konkrete abgeleitete Klassen sein)

UND

Die Schnittstelle wird verwendet für Kommunikation zwischen 2 ähnlichen/nicht ähnlichen Klassen, die sich nicht um den Typ der Klasse kümmern, die die Schnittstelle implementiert (z.B. Höhe kann eine Schnittstelleneigenschaft sein und sie kann von Mensch, Gebäude, Baum implementiert werden. Es spielt keine Rolle, ob Sie essen können, können Sie schwimmen, können Sie sterben oder irgendetwas es zählt nur eine Sache, die Sie benötigen, um Höhe (Implementierung in Sie Klasse) haben).

11 Stimmen

Diese Antwort gefällt mir sehr gut, weil es manchmal schwierig ist, die Frage nach dem "Was" zwischen den Dingen zu beantworten, wenn man etwas Abstrakteres betrachtet, wie z. B. intento anstelle von nur Struktur (da eine Schnittstelle und eine rein abstrakte Klasse strukturell gesehen so ziemlich dasselbe sind).

0 Stimmen

Es ist einfach aufzuzählen, was eine abstrakte Klasse bzw. eine Schnittstelle in einer bestimmten Sprache tun kann, aber es ist schwieriger, eine Abstraktion zu schaffen, um dem Objekt Bedeutung und Verantwortung zu geben, und was Sie gesagt haben, fasst die Verwendung der beiden Konzepte in OO vollständig zusammen. Danke!

2 Stimmen

@dhananjay: Ich verstehe, wie Height vom Konzept der Klasse Animal getrennt sein kann und von einer anderen Klasse stammen kann, aber was genau meinen Sie mit "Kommunikation" zwischen den Klassen? Es ist einfach nur die Definition von Höhe für seine eigene Klasse, richtig?

82voto

Reed Copsey Punkte 536986

Es gibt noch ein paar andere Unterschiede -

Schnittstellen können keine konkreten Implementierungen haben. Abstrakte Basisklassen können das. Dies ermöglicht es Ihnen, dort konkrete Implementierungen bereitzustellen. Dadurch kann eine abstrakte Basisklasse einen strengeren Vertrag bieten, während eine Schnittstelle eigentlich nur beschreibt, wie eine Klasse verwendet wird. (Die abstrakte Basisklasse kann nicht-virtuelle Mitglieder haben, die das Verhalten definieren, was dem Autor der Basisklasse mehr Kontrolle gibt.)

In einer Klasse kann mehr als eine Schnittstelle implementiert werden. Eine Klasse kann nur von einer einzigen abstrakten Basisklasse abgeleitet werden. Dies ermöglicht eine polymorphe Hierarchie unter Verwendung von Schnittstellen, aber 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 zerstören. Änderungen an Schnittstellen sind Änderungen, die zum Bruch führen.

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

7 Stimmen

+1 für den wichtigen Punkt, dass mehr als eine Schnittstelle in einer Klasse implementiert werden kann.

0 Stimmen

Das ist der einzige wirkliche Vorteil von Schnittstellen gegenüber abstrakten Basisklassen, IMO. Ansonsten stimme ich mit den .NET-Entwurfsrichtlinien überein, die nun besagen, dass man "abstrakte Basisklassen gegenüber Schnittstellen bevorzugen sollte".

0 Stimmen

Allerdings wäre es gut, wenn Sie den Punkt hinzufügen könnten, dass die Schnittstellen auch auf jede Klasse angewendet werden können.

70voto

itsfarseen Punkte 1142

Vererbung
Erwägen Sie ein Auto und einen Bus. Sie sind zwei verschiedene Fahrzeuge. Dennoch haben sie einige gemeinsame Eigenschaften wie Lenkung, Bremsen, Getriebe, Motor usw.
Mit dem Konzept der Vererbung 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 Grundformen und deren Kinder zu klassifizieren, wie wir oben gesehen haben.

Abstrakte Klassen

Abstrakte Klassen sind unvollständig Objekte. Um dies besser zu verstehen, lassen Sie uns noch einmal die Analogie zum Fahrzeug betrachten.
Ein Fahrzeug kann gefahren werden. Oder? Aber verschiedene Fahrzeuge werden auf verschiedene Weise gefahren ... Zum Beispiel kann man ein Auto nicht so fahren, wie man ein Fahrrad fährt.
Wie kann man nun die Antriebsfunktion 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 die Klasse Driver immer wieder ändern, wenn Sie einen neuen Fahrzeugtyp hinzufügen.
Hier kommt die Rolle der abstrakten Klassen und Methoden ins Spiel. Sie können die Drive-Methode als abstrakt definieren, um anzugeben, dass alle vererbenden Kinder diese Funktion implementieren müssen.
Wenn Sie also die Fahrzeugklasse ändern ...

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

Das Fahrrad und das Auto müssen auch angeben, wie es gefahren werden soll. Andernfalls lässt sich der Code nicht kompilieren und es wird ein Fehler ausgegeben.
Kurz gesagt: Eine abstrakte Klasse ist eine teilweise unvollständige Klasse mit einigen unvollständigen Funktionen, die die vererbenden Kinder selbst angeben müssen.

Schnittstellen Die Schnittstellen sind völlig unvollständig. Sie haben keine Eigenschaften. Sie zeigen lediglich an, dass die vererbenden Kinder in der Lage sind, etwas zu tun ...
Angenommen, Sie haben verschiedene Arten von Mobiltelefonen dabei. Jedes von ihnen hat unterschiedliche Möglichkeiten, verschiedene Funktionen auszuführen, z. B. eine Person anzurufen. Der Hersteller des Telefons legt fest, wie das geht. Hier können die Mobiltelefone eine Nummer wählen - das heißt, sie sind wählbar. Lassen Sie uns dies als Schnittstelle darstellen.

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

Hier definiert der Hersteller des Dialable, wie eine Nummer zu wählen ist. 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);
}
.....

Durch die Verwendung von Schnittstellen anstelle von abstrakten Klassen muss sich der Autor der Funktion, die ein Dialable verwendet, nicht um dessen 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; ob es die Schnittstelle Dialable erbt (oder implementiert).

Und was noch wichtiger ist wenn Sie eines Tages das Wählbare durch ein anderes ersetzen

......
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 die Wählscheibe verwendet, nicht von anderen Details abhängt (und auch nicht abhängen kann) als denen, die in der Wählscheibenschnittstelle angegeben sind. Beide implementieren eine Wählbarkeitsschnittstelle, und das ist das Einzige, was die Funktion interessiert.

Schnittstellen werden üblicherweise von Entwicklern verwendet, um die Interoperabilität (austauschbare Verwendung) zwischen Objekten zu gewährleisten, sofern sie eine gemeinsame Funktion haben (so 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 jegliche Eigenschaften.
Beachten Sie auch, dass Sie beliebig viele Schnittstellen implementieren (erben) können, aber nur eine einzige übergeordnete Klasse erweitern (erben) können.

Mehr Infos Abstrakte Klassen vs. Interfaces

0 Stimmen

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

0 Stimmen

@Bigeyes, Java erlaubt keine Eigenschaften in Schnittstellen. Ich dachte, das wäre in anderen Sprachen auch so. Könnten Sie das bitte näher erläutern?

0 Stimmen

Ich beziehe mich auf C#/.Net. Bitte sehen Sie die Beispiel

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X