Was genau ist der Unterschied zwischen einer Schnittstelle und einer abstrakten Klasse?
Was genau ist der Unterschied zwischen einer Schnittstelle und einer abstrakten Klasse?
Antworten:
Eine Schnittstelle ist ein Vertrag : Die Person, die die Schnittstelle schreibt, sagt: " Hey, ich akzeptiere Dinge, die so aussehen ", und die Person, die die Schnittstelle verwendet, sagt " OK, die Klasse, die ich schreibe, sieht so aus ".
Eine Schnittstelle ist eine leere Shell . Es gibt nur die Signaturen der Methoden, was bedeutet, dass die Methoden keinen Körper haben. Die Schnittstelle kann nichts tun. Es ist nur ein Muster.
Zum Beispiel (Pseudocode):
// I say all motor vehicles should look like this:
interface MotorVehicle
{
void run();
int getFuel();
}
// My team mate complies and writes vehicle looking that way
class Car implements MotorVehicle
{
int fuel;
void run()
{
print("Wrroooooooom");
}
int getFuel()
{
return this.fuel;
}
}
Das Implementieren einer Schnittstelle verbraucht sehr wenig CPU, da es sich nicht um eine Klasse, sondern nur um eine Reihe von Namen handelt und daher keine teure Suche erforderlich ist. Es ist großartig, wenn es darauf ankommt, beispielsweise bei eingebetteten Geräten.
Abstrakte Klassen sind im Gegensatz zu Schnittstellen Klassen. Ihre Verwendung ist teurer, da beim Nacherben von ihnen nachgeschlagen werden muss.
Abstrakte Klassen sehen Schnittstellen sehr ähnlich, haben aber noch etwas mehr: Sie können ein Verhalten für sie definieren. Es geht eher um eine Person, die sagt: " Diese Klassen sollten so aussehen, und sie haben das gemeinsam, also füllen Sie die Lücken aus! ".
Zum Beispiel:
// I say all motor vehicles should look like this:
abstract class MotorVehicle
{
int fuel;
// They ALL have fuel, so lets implement this for everybody.
int getFuel()
{
return this.fuel;
}
// That can be very different, force them to provide their
// own implementation.
abstract void run();
}
// My teammate complies and writes vehicle looking that way
class Car extends MotorVehicle
{
void run()
{
print("Wrroooooooom");
}
}
Während abstrakte Klassen und Schnittstellen unterschiedliche Konzepte sein sollen, machen die Implementierungen diese Aussage manchmal unwahr. Manchmal sind sie nicht einmal das, was Sie denken.
In Java wird diese Regel stark durchgesetzt, während in PHP Schnittstellen abstrakte Klassen ohne deklarierte Methode sind.
In Python sind abstrakte Klassen eher ein Programmiertrick, den Sie vom ABC-Modul erhalten können, und verwenden tatsächlich Metaklassen und damit Klassen. Und Schnittstellen beziehen sich eher auf die Eingabe von Enten in dieser Sprache und es ist eine Mischung aus Konventionen und speziellen Methoden, die Deskriptoren aufrufen (die __method__-Methoden).
Wie beim Programmieren üblich, gibt es Theorie, Praxis und Praxis in einer anderen Sprache :-)
interface
und class
von Head First Java
ist lebendig, dassA class defines who you are, and an interface tells what roles you could play
Die wichtigsten technischen Unterschiede zwischen einer abstrakten Klasse und einer Schnittstelle sind:
Abstrakte Klassen können Konstanten, Mitglieder, Methodenstubs (Methoden ohne Body) und definierte Methoden haben , während Schnittstellen nur Konstanten und Methodenstubs haben können .
Methoden und Mitglieder einer abstrakten Klasse können mit jeder Sichtbarkeit definiert werden , während alle Methoden einer Schnittstelle als definiert werden müssen public
(sie sind standardmäßig öffentlich definiert).
Beim Erben einer abstrakten Klasse muss eine konkrete untergeordnete Klasse die abstrakten Methoden definieren , während eine abstrakte Klasse eine andere abstrakte Klasse erweitern kann und abstrakte Methoden aus der übergeordneten Klasse nicht definiert werden müssen.
In ähnlicher Weise ist eine Schnittstelle, die eine andere Schnittstelle erweitert, nicht für die Implementierung von Methoden von der übergeordneten Schnittstelle verantwortlich. Dies liegt daran, dass Schnittstellen keine Implementierung definieren können.
Eine untergeordnete Klasse kann nur eine einzelne Klasse (abstrakt oder konkret) erweitern, während eine Schnittstelle erweitert werden kann oder eine Klasse mehrere andere Schnittstellen implementieren kann .
Eine untergeordnete Klasse kann abstrakte Methoden mit derselben oder einer weniger restriktiven Sichtbarkeit definieren , während eine Klasse, die eine Schnittstelle implementiert, die Methoden mit genau derselben Sichtbarkeit (öffentlich) definieren muss.
CANNOT
instanziiert werden.
Eine Schnittstelle enthält nur die Definition / Signatur der Funktionalität. Wenn wir einige gemeinsame Funktionen sowie gemeinsame Signaturen haben, müssen wir eine abstrakte Klasse verwenden. Durch die Verwendung einer abstrakten Klasse können wir sowohl Verhalten als auch Funktionalität gleichzeitig bereitstellen. Ein anderer Entwickler, der eine abstrakte Klasse erbt, kann diese Funktionalität problemlos verwenden, da nur die Lücken ausgefüllt werden müssen.
http://www.dotnetbull.com/2011/11/difference-between-abstract-class-and.html
http://www.dotnetbull.com/2011/11/what-is-abstract-class-in-c-net.html http://www.dotnetbull.com/2011/11/what-is-interface-in -c-net.html
Eine Erklärung finden Sie hier: http://www.developer.com/lang/php/article.php/3604111/PHP-5-OOP-Interfaces-Abstract-Classes-and-the-Adapter-Pattern.htm
Eine abstrakte Klasse ist eine Klasse, die vom Programmierer nur teilweise implementiert wird. Es kann eine oder mehrere abstrakte Methoden enthalten. Eine abstrakte Methode ist einfach eine Funktionsdefinition, die dem Programmierer mitteilt, dass die Methode in einer untergeordneten Klasse implementiert werden muss.
Eine Schnittstelle ähnelt einer abstrakten Klasse. In der Tat belegen Schnittstellen denselben Namespace wie Klassen und abstrakte Klassen. Aus diesem Grund können Sie keine Schnittstelle mit demselben Namen wie eine Klasse definieren. Eine Schnittstelle ist eine vollständig abstrakte Klasse. Keine seiner Methoden ist implementiert, und anstelle einer Klassenunterklassifizierung soll diese Schnittstelle implementiert werden.
Jedenfalls finde ich diese Erklärung der Schnittstellen etwas verwirrend. Eine häufigere Definition lautet: Eine Schnittstelle definiert einen Vertrag, den implementierende Klassen erfüllen müssen. Eine Schnittstellendefinition besteht aus Signaturen öffentlicher Mitglieder ohne Implementierungscode.
Ich möchte nicht auf die Unterschiede hinweisen, die bereits in vielen Antworten erwähnt wurden (in Bezug auf öffentliche statische Endmodifikatoren für Variablen in der Schnittstelle und Unterstützung für geschützte, private Methoden in abstrakten Klassen).
In einfachen Worten möchte ich sagen:
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
Aus der Oracle- Dokumentation
Verwenden Sie abstrakte Klassen, wenn:
Erwägen Sie die Verwendung von Schnittstellen, wenn:
Serializable
Schnittstelle implementieren .abstrakte Klasse stellt "ist eine" Beziehung zu konkreten Klassen her. Schnittstelle bietet "hat eine" Fähigkeit für Klassen.
Wenn Sie Java
als Programmiersprache suchen , finden Sie hier einige weitere Updates:
Java 8 hat die Lücke zwischen interface
und abstract
Klassen durch die Bereitstellung einer default
Methodenfunktion in gewissem Maße verringert . Eine Schnittstelle hat keine Implementierung für eine Methode, die jetzt nicht mehr gültig ist.
Siehe diese Dokumentation Seite für weitere Details.
In dieser SE-Frage finden Sie Codebeispiele, um sie besser zu verstehen.
Wie hätte ich den Unterschied zwischen einer Interface- und einer Abstract-Klasse erklären sollen?
Einige wichtige Unterschiede:
In Form einer Tabelle:
Wie von Joe aus Javapapers angegeben :
1. Der Hauptunterschied besteht darin, dass Methoden einer Java-Schnittstelle implizit abstrakt sind und keine Implementierungen haben können. Eine abstrakte Java-Klasse kann Instanzmethoden haben, die ein Standardverhalten implementieren.
2.Variablen, die in einer Java-Schnittstelle deklariert sind, sind standardmäßig final. Eine abstrakte Klasse kann nicht endgültige Variablen enthalten.
3. Mitglieder einer Java-Schnittstelle sind standardmäßig öffentlich. Eine abstrakte Java-Klasse kann die üblichen Varianten von Klassenmitgliedern wie privat, geschützt usw. haben.
4. Die Java-Schnittstelle sollte mit dem Schlüsselwort "implementiert" implementiert werden. Eine abstrakte Java-Klasse sollte mit dem Schlüsselwort "erweitert" erweitert werden.
5. Eine Schnittstelle kann nur eine andere Java-Schnittstelle erweitern, eine abstrakte Klasse kann eine andere Java-Klasse erweitern und mehrere Java-Schnittstellen implementieren.
6. Eine Java-Klasse kann mehrere Schnittstellen implementieren, jedoch nur eine abstrakte Klasse erweitern.
7. Die Schnittstelle ist absolut abstrakt und kann nicht instanziiert werden. Eine abstrakte Java-Klasse kann ebenfalls nicht instanziiert werden, kann jedoch aufgerufen werden, wenn ein main () vorhanden ist.
8. Im Vergleich zu abstrakten Java-Klassen sind Java-Schnittstellen langsam, da zusätzliche Indirektion erforderlich ist.
Der Hauptpunkt ist, dass:
Ich baue ein Gebäude mit 300 Stockwerken
Der Bauplan des Gebäudes Schnittstelle
Gebäude mit bis zu 200 Stockwerken - teilweise fertiggestellt --- abstrakt
Hochbau fertiggestellt - Beton
Schnittstelle
Abstrakt
Entnommen der DurgaJobs-Website
Lassen Sie uns noch einmal an dieser Frage arbeiten:
Das erste, was Sie wissen lassen müssen, ist, dass 1/1 und 1 * 1 dasselbe ergeben, aber dies bedeutet nicht, dass Multiplikation und Division gleich sind. Offensichtlich haben sie eine gute Beziehung, aber wohlgemerkt, beide sind unterschiedlich.
Ich werde auf die Hauptunterschiede hinweisen, und der Rest wurde bereits erklärt:
Abstrakte Klassen sind nützlich zum Modellieren einer Klassenhierarchie. Auf den ersten Blick ist uns teilweise klar, was genau gebaut werden soll, aber wir wissen, was zu bauen ist. Und so sind Ihre abstrakten Klassen Ihre Basisklassen.
Schnittstellen sind nützlich, um anderen Hierarchien oder Klassen mitzuteilen, wozu ich in der Lage bin. Und wenn Sie sagen, dass ich zu etwas fähig bin, müssen Sie diese Fähigkeit haben. Schnittstellen markieren, dass eine Klasse dieselben Funktionen implementieren muss.
Es ist eigentlich ziemlich einfach.
Sie können sich eine Schnittstelle als eine Klasse vorstellen, die nur abstrakte Methoden und nichts anderes haben darf.
Eine Schnittstelle kann also nur das Verhalten "deklarieren" und nicht definieren, das die Klasse haben soll.
Mit einer abstrakten Klasse können Sie sowohl das Verhalten der Klasse deklarieren (mit abstrakten Methoden) als auch definieren (mit vollständigen Methodenimplementierungen).
In einer regulären Klasse können Sie nur das Verhalten / die Aktionen definieren und nicht deklarieren, die die Klasse haben soll.
Eine letzte Sache,
In Java können Sie mehrere Schnittstellen implementieren, aber nur eine (abstrakte Klasse oder Klasse) erweitern ...
Dies bedeutet, dass die Vererbung von definiertem Verhalten nur eine pro Klasse zulässt. Wenn Sie also eine Klasse möchten, die Verhalten aus den Klassen A, B und C kapselt, müssen Sie Folgendes tun: Klasse A erweitert B, Klasse C erweitert A .. Es ist eine Art Umweg über Mehrfachvererbung ...
Schnittstellen hingegen können Sie einfach tun: Schnittstelle C implementiert A, B.
In der Tat unterstützt Java die Mehrfachvererbung nur in "deklariertem Verhalten", dh Schnittstellen, und nur die Einzelvererbung mit definiertem Verhalten.
Hoffentlich macht das Sinn.
Der Vergleich von Schnittstelle zu abstrakter Klasse ist falsch. Stattdessen sollten zwei weitere Vergleiche durchgeführt werden: 1) Schnittstelle vs. Klasse und 2) Zusammenfassung vs. Endklasse .
Schnittstelle ist ein Vertrag zwischen zwei Objekten. ZB bin ich ein Postbote und du bist ein Paket zu liefern. Ich erwarte, dass Sie Ihre Lieferadresse kennen. Wenn mir jemand ein Paket gibt, muss er seine Lieferadresse kennen:
interface Package {
String address();
}
Klasse ist eine Gruppe von Objekten, die dem Vertrag gehorchen. ZB bin ich eine Box aus der "Box" -Gruppe und halte mich an den vom Postboten geforderten Vertrag. Gleichzeitig gehorche ich anderen Verträgen:
class Box implements Package, Property {
@Override
String address() {
return "5th Street, New York, NY";
}
@Override
Human owner() {
// this method is part of another contract
}
}
Die abstrakte Klasse ist eine Gruppe unvollständiger Objekte. Sie können nicht verwendet werden, da ihnen einige Teile fehlen. ZB bin ich eine abstrakte GPS-fähige Box - ich weiß, wie ich meine Position auf der Karte überprüfen kann:
abstract class GpsBox implements Package {
@Override
public abstract String address();
protected Coordinates whereAmI() {
// connect to GPS and return my current position
}
}
Diese Klasse kann sehr nützlich sein, wenn sie von einer anderen Klasse geerbt / erweitert wird. Aber an sich - es ist nutzlos, da es keine Objekte haben kann. Abstrakte Klassen können Elemente von Abschlussklassen sein.
Die letzte Klasse ist eine Gruppe vollständiger Objekte, die verwendet, aber nicht geändert werden können. Sie wissen genau, wie man arbeitet und was zu tun ist. Ich bin beispielsweise eine Box, die immer an die Adresse geht, die während der Erstellung angegeben wurde:
final class DirectBox implements Package {
private final String to;
public DirectBox(String addr) {
this.to = addr;
}
@Override
public String address() {
return this.to;
}
}
In den meisten Sprachen wie Java oder C ++ ist es möglich, nur eine Klasse zu haben , weder abstrakt noch endgültig. Eine solche Klasse kann vererbt und instanziiert werden. Ich denke jedoch nicht, dass dies streng im Einklang mit dem objektorientierten Paradigma steht.
Auch hier ist der Vergleich von Schnittstellen mit abstrakten Klassen nicht korrekt.
Kurz gesagt, die Unterschiede sind folgende:
Syntaktische Unterschiede zwischen Schnittstelle und abstrakter Klasse :
In Interfaces jetzt:
public static
- unterstützt
public abstract
- unterstützt
public default
- unterstützt
private static
- unterstützt
private abstract
- Kompilierungsfehler
private default
- Kompilierungsfehler
private
- unterstützt
Der einzige Unterschied besteht darin, dass man an Mehrfachvererbung teilnehmen kann und andere nicht.
Die Definition einer Schnittstelle hat sich im Laufe der Zeit geändert. Denken Sie, dass eine Schnittstelle nur Methodendeklarationen enthält und nur Verträge sind? Was ist mit statischen Endvariablen und was ist mit Standarddefinitionen nach Java 8?
Schnittstellen wurden aufgrund des Diamantproblems mit Mehrfachvererbung in Java eingeführt, und genau das beabsichtigen sie tatsächlich zu tun.
Schnittstellen sind die Konstrukte, die erstellt wurden, um das Problem der Mehrfachvererbung zu lösen. Sie können abstrakte Methoden, Standarddefinitionen und statische Endvariablen enthalten.
Schnittstelle: Abbiegen (links abbiegen, rechts abbiegen.)
Abstrakte Klasse: Rad.
Klasse: Lenkrad, stammt vom Rad, legt die Schnittstellendrehung frei
Eine dient zur Kategorisierung von Verhalten, das für eine Vielzahl von Dingen angeboten werden kann, die andere zur Modellierung einer Ontologie von Dingen.
Wenn Sie einige allgemeine Methoden haben, die von mehreren Klassen verwendet werden können, wählen Sie abstrakte Klassen. Wenn Sie möchten, dass die Klassen einem bestimmten Entwurf folgen, wählen Sie Schnittstellen.
Die folgenden Beispiele zeigen dies.
Abstrakte Klasse in Java:
abstract class animals
{
// They all love to eat. So let's implement them for everybody
void eat()
{
System.out.println("Eating...");
}
// The make different sounds. They will provide their own implementation.
abstract void sound();
}
class dog extends animals
{
void sound()
{
System.out.println("Woof Woof");
}
}
class cat extends animals
{
void sound()
{
System.out.println("Meoww");
}
}
Es folgt eine Implementierung der Schnittstelle in Java:
interface Shape
{
void display();
double area();
}
class Rectangle implements Shape
{
int length, width;
Rectangle(int length, int width)
{
this.length = length;
this.width = width;
}
@Override
public void display()
{
System.out.println("****\n* *\n* *\n****");
}
@Override
public double area()
{
return (double)(length*width);
}
}
class Circle implements Shape
{
double pi = 3.14;
int radius;
Circle(int radius)
{
this.radius = radius;
}
@Override
public void display()
{
System.out.println("O"); // :P
}
@Override
public double area()
{
return (double)((pi*radius*radius)/2);
}
}
Einige wichtige wichtige Punkte auf den Punkt gebracht:
Die in der Java-Schnittstelle deklarierten Variablen sind standardmäßig final. Abstrakte Klassen können nicht endgültige Variablen haben.
Die in der Java-Schnittstelle deklarierten Variablen sind standardmäßig statisch. Abstrakte Klassen können nicht statische Variablen haben.
Mitglieder einer Java-Schnittstelle sind standardmäßig öffentlich. Eine abstrakte Java-Klasse kann die üblichen Varianten von Klassenmitgliedern wie privat, geschützt usw. haben.
Viele Nachwuchsentwickler machen den Fehler, Schnittstellen, abstrakte und konkrete Klassen als geringfügige Abweichungen derselben zu betrachten, und wählen eine davon nur aus technischen Gründen: Brauche ich Mehrfachvererbung? Benötige ich einen Platz, um gängige Methoden anzuwenden? Muss ich mich mit etwas anderem als nur einer konkreten Klasse beschäftigen? Das ist falsch und in diesen Fragen verbirgt sich das Hauptproblem: "Ich" . Wenn Sie selbst Code schreiben, denken Sie selten an andere gegenwärtige oder zukünftige Entwickler, die an oder mit Ihrem Code arbeiten.
Schnittstellen und abstrakte Klassen haben, obwohl sie aus technischer Sicht offensichtlich ähnlich sind, völlig unterschiedliche Bedeutungen und Zwecke.
Eine Schnittstelle definiert einen Vertrag , den eine Implementierung für Sie erfüllen wird .
Eine abstrakte Klasse bietet ein Standardverhalten, das Ihre Implementierung wiederverwenden kann.
Eine konkrete Klasse erledigt die eigentliche Arbeit auf ganz bestimmte Weise. Beispielsweise ArrayList
verwendet a einen zusammenhängenden Speicherbereich, um eine Liste von Objekten auf kompakte Weise zu speichern, die schnellen Direktzugriff, Iteration und direkte Änderungen bietet, aber beim Einfügen, Löschen und gelegentlich sogar beim Hinzufügen schrecklich ist. In der Zwischenzeit LinkedList
verwendet a doppelt verknüpfte Knoten, um eine Liste von Objekten zu speichern, die stattdessen eine schnelle Iteration, direkte Änderungen und das Einfügen / Löschen / Hinzufügen bietet, aber bei wahlfreiem Zugriff schrecklich ist. Diese beiden Arten von Listen sind für verschiedene Anwendungsfälle optimiert, und es ist sehr wichtig, wie Sie sie verwenden werden. Wenn Sie versuchen, die Leistung aus einer Liste herauszuholen, mit der Sie stark interagieren, und wenn Sie die Art der Liste auswählen, sollten Sie sorgfältig auswählen, welche Sie instanziieren.
Auf der anderen Seite ist es hochrangigen Benutzern einer Liste egal, wie sie tatsächlich implementiert wird, und sie sollten von diesen Details isoliert sein. Stellen wir uns vor, Java hat die List
Schnittstelle nicht verfügbar gemacht , sondern nur eine konkrete List
Klasse, die LinkedList
genau das ist, was gerade ist. Alle Java-Entwickler hätten ihren Code an die Implementierungsdetails angepasst: Vermeiden Sie Direktzugriff, fügen Sie einen Cache hinzu, um den Zugriff zu beschleunigen, oder implementieren ArrayList
Sie ihn einfach selbst neu, obwohl er nicht mit allen anderen Codes kompatibel wäre, die tatsächlich nur funktionieren List
. Das wäre schrecklich ... Aber stellen Sie sich jetzt vor, dass die Java-Master tatsächlich erkennen, dass eine verknüpfte Liste für die meisten tatsächlichen Anwendungsfälle schrecklich ist, und beschlossen, nur für ihre auf eine Array-Liste umzuschaltenList
Klasse verfügbar. Dies würde die Leistung jedes Java-Programms auf der Welt beeinträchtigen, und die Leute würden sich nicht darüber freuen. Der Hauptschuldige ist, dass Implementierungsdetails verfügbar waren, und die Entwickler gingen davon aus, dass diese Details ein dauerhafter Vertrag sind, auf den sie sich verlassen können. Aus diesem Grund ist es wichtig, Implementierungsdetails auszublenden und nur einen abstrakten Vertrag zu definieren. Dies ist der Zweck einer Schnittstelle: Definieren Sie, welche Art von Eingabe eine Methode akzeptiert und welche Art von Ausgabe erwartet wird, ohne alle Eingeweide aufzudecken, die Programmierer dazu verleiten würden, ihren Code so anzupassen, dass er den internen Details entspricht, die sich bei zukünftigen Updates ändern könnten .
Eine abstrakte Klasse befindet sich in der Mitte zwischen Schnittstellen und konkreten Klassen. Es soll Implementierungen helfen, gemeinsamen oder langweiligen Code zu teilen. Zum Beispiel AbstractCollection
bietet grundlegende Implementierungen für isEmpty
basierend auf der Größe 0 ist, contains
als Iterierte und vergleichen, addAll
wie wiederholtadd
, und so weiter. Auf diese Weise können sich Implementierungen auf die entscheidenden Teile konzentrieren, die zwischen ihnen unterscheiden: das tatsächliche Speichern und Abrufen von Daten.
Schnittstellen sind Gateways mit geringer Kohäsion zwischen verschiedenen Teilen des Codes. Sie ermöglichen es Bibliotheken, zu existieren und sich weiterzuentwickeln, ohne jeden Bibliotheksbenutzer zu beschädigen, wenn sich intern etwas ändert. Es heißt Application Programming Interface - nicht Application Programming Klassen. In kleinerem Maßstab ermöglichen sie auch mehreren Entwicklern die erfolgreiche Zusammenarbeit bei großen Projekten, indem sie verschiedene Module durch gut dokumentierte Schnittstellen trennen.
Abstrakte Klassen sind hochkohäsive Helfer , die bei der Implementierung einer Schnittstelle verwendet werden können, sofern ein gewisses Maß an Implementierungsdetails vorausgesetzt wird. Alternativ werden abstrakte Klassen zum Definieren von SPIs (Service Provider Interfaces) verwendet.
Der Unterschied zwischen einer API und einem SPI ist subtil, aber wichtig: Bei einer API liegt der Fokus darauf, wer sie verwendet , und bei einem SPI liegt der Fokus darauf, wer sie implementiert .
Das Hinzufügen von Methoden zu einer API ist einfach. Alle vorhandenen Benutzer der API werden weiterhin kompiliert. Das Hinzufügen von Methoden zu einem SPI ist schwierig, da jeder Dienstanbieter (konkrete Implementierung) die neuen Methoden implementieren muss. Wenn zum Definieren eines SPI Schnittstellen verwendet werden, muss ein Anbieter bei jeder Änderung des SPI-Vertrags eine neue Version veröffentlichen. Wenn stattdessen abstrakte Klassen verwendet werden, können neue Methoden entweder als vorhandene abstrakte Methoden oder als leere throw not implemented exception
Stubs definiert werden, wodurch zumindest eine ältere Version einer Service-Implementierung weiterhin kompiliert und ausgeführt werden kann.
Obwohl Java 8 Standardmethoden für Schnittstellen eingeführt hat, die die Grenze zwischen Schnittstellen und abstrakten Klassen noch unschärfer machen, war dies nicht so, dass Implementierungen Code wiederverwenden können, sondern um das Ändern von Schnittstellen zu erleichtern, die sowohl als API als auch als SPI dienen (oder werden fälschlicherweise zum Definieren von SPIs anstelle von abstrakten Klassen verwendet).
Eine Konsequenz: Der umgekehrte Weg wird oft falsch gemacht: Wenn Sie etwas verwenden , versuchen Sie immer, die allgemeinste Klasse / Schnittstelle zu verwenden, die Sie tatsächlich benötigen. Mit anderen Worten, deklarieren Sie Ihre Variablen nicht als ArrayList theList = new ArrayList()
, es sei denn, Sie haben tatsächlich eine sehr starke Abhängigkeit davon, dass es sich um eine Array- Liste handelt, und kein anderer Listentyp würde sie für Sie ausschneiden. Verwenden Sie List theList = new ArrayList
stattdessen oder auch Collection theCollection = new ArrayList
wenn die Tatsache, dass es sich um eine Liste handelt und keine andere Art von Sammlung, keine Rolle spielt.
Nicht wirklich die Antwort auf die ursprüngliche Frage, aber sobald Sie die Antwort auf den Unterschied zwischen ihnen haben, werden Sie in das Dilemma der Verwendungsmöglichkeiten für jedes eingehen: Wann werden Schnittstellen oder abstrakte Klassen verwendet? Wann beides verwenden?
Ich habe nur begrenzte Kenntnisse über OOP, aber Schnittstellen als Äquivalent eines Adjektivs in der Grammatik zu sehen, hat bis jetzt für mich funktioniert (korrigieren Sie mich, wenn diese Methode falsch ist!). Beispielsweise sind Schnittstellennamen wie Attribute oder Funktionen, die Sie einer Klasse geben können, und eine Klasse kann viele davon haben: ISerializable, ICountable, IList, ICacheable, IHappy, ...
Die Vererbung wird für zwei Zwecke verwendet:
Damit ein Objekt übergeordnete Datenelemente und Methodenimplementierungen als seine eigenen betrachten kann.
Damit kann ein Verweis auf ein Objekt eines Typs von Code verwendet werden, der einen Verweis auf ein Objekt vom Supertyp erwartet.
In Sprachen / Frameworks, die eine verallgemeinerte Mehrfachvererbung unterstützen, besteht häufig nur eine geringe Notwendigkeit, einen Typ entweder als "Schnittstelle" oder als "abstrakte Klasse" zu klassifizieren. In gängigen Sprachen und Frameworks kann ein Typ jedoch die Datenelemente oder Methodenimplementierungen eines anderen Typs als seine eigenen betrachten, obwohl ein Typ durch eine beliebige Anzahl anderer Typen ersetzt werden kann.
Abstrakte Klassen können Datenelemente und Methodenimplementierungen haben, können jedoch nur von Klassen geerbt werden, die keine anderen Klassen erben. Schnittstellen beschränken die Typen, die sie implementieren, fast nicht, können jedoch keine Datenelemente oder Methodenimplementierungen enthalten.
Es gibt Zeiten, in denen es nützlich ist, wenn Typen durch viele verschiedene Dinge ersetzt werden können. Es gibt andere Zeiten, in denen es für Objekte nützlich ist, übergeordnete Datenelemente und Methodenimplementierungen als ihre eigenen zu betrachten. Durch die Unterscheidung zwischen Schnittstellen und abstrakten Klassen kann jede dieser Fähigkeiten in Fällen eingesetzt werden, in denen sie am relevantesten ist.
Wichtige Punkte:
Vorteil:
Details finden Sie hier ... http://pradeepatkari.wordpress.com/2014/11/20/interface-and-abstract-class-in-c-oops/
Der kürzeste Weg, um es zusammenzufassen, interface
ist:
default
und static
Methoden; Während es Definitionen (Methodensignaturen + Implementierungen) für default
und static
Methoden enthält, enthält es nur Deklarationen (Methodensignaturen) für andere Methoden.interface
s implementieren und eine interface
von mehreren interface
s erben ). Alle Variablen sind implizit konstant, unabhängig davon, ob sie als angegeben sind public static final
oder nicht. Alle Mitglieder sind implizit public
, ob als solche angegeben oder nicht.Inzwischen ist eine abstract
Klasse:
abstract
Methoden zu haben. Kann sowohl Deklarationen als auch Definitionen enthalten, wobei die Deklarationen als gekennzeichnet sind abstract
.protected
, private
oder privates Paket (nicht spezifiziert).Oder wenn wir alles auf einen einzigen Satz reduzieren wollen: An interface
ist das, was die implementierende Klasse hat , aber eine abstract
Klasse ist das, was die Unterklasse ist .
Ich möchte noch einen Unterschied hinzufügen, der Sinn macht. Sie haben beispielsweise ein Framework mit Tausenden von Codezeilen. Wenn Sie nun mit einer Methode boostUI () eine neue Funktion im gesamten Code hinzufügen möchten, ist es besser, diese Methode in der abstrakten Klasse und nicht in der Schnittstelle hinzuzufügen. Wenn Sie diese Methode in eine Schnittstelle einfügen, sollten Sie sie in der gesamten implementierten Klasse implementieren. Dies ist jedoch nicht der Fall, wenn Sie die Methode in der abstrakten Klasse hinzufügen.
Um eine einfache, aber klare Antwort zu geben, ist es hilfreich, den Kontext festzulegen: Sie verwenden beide, wenn Sie keine vollständigen Implementierungen bereitstellen möchten.
Der Hauptunterschied besteht dann darin, dass eine Schnittstelle überhaupt keine Implementierung hat (nur Methoden ohne Body), während abstrakte Klassen auch Mitglieder und Methoden mit einem Body haben können, dh teilweise implementiert werden können.
default
Schlüsselwort in Java 8, mit dem Sie konkrete Methoden auch in Schnittstellen definieren können.
Unterschiede zwischen abstrakter Klasse und Schnittstelle im Namen der tatsächlichen Implementierung.
Schnittstelle : Es ist ein Schlüsselwort und wird zum Definieren der Vorlage oder des Entwurfs eines Objekts verwendet. Es erzwingt, dass alle Unterklassen demselben Prototyp folgen, da bei der Implementierung alle Unterklassen frei sind, die Funktionalität gemäß zu implementieren es ist Voraussetzung.
Einige andere Anwendungsfälle, in denen wir die Schnittstelle verwenden sollten.
Kommunikation zwischen zwei externen Objekten (Integration durch Dritte in unsere Anwendung) über Interface here Interface funktioniert als Vertrag.
Abstrakte Klasse: Abstrakt, es ist ein Schlüsselwort, und wenn wir dieses Schlüsselwort vor einer Klasse verwenden, wird es zu einer abstrakten Klasse. Es wird hauptsächlich verwendet, wenn wir die Vorlage sowie einige Standardfunktionen eines Objekts definieren müssen, denen alle folgen Unterklassen und auf diese Weise wird der redundante Code entfernt und ein weiterer Anwendungsfall, in dem wir abstrakte Klassen verwenden können , wie wir möchten, dass keine anderen Klassen ein Objekt der Klasse direkt instanziieren können, nur abgeleitete Klassen können die Funktionalität verwenden.
Beispiel für eine abstrakte Klasse:
public abstract class DesireCar
{
//It is an abstract method that defines the prototype.
public abstract void Color();
// It is a default implementation of a Wheel method as all the desire cars have the same no. of wheels.
// and hence no need to define this in all the sub classes in this way it saves the code duplicasy
public void Wheel() {
Console.WriteLine("Car has four wheel");
}
}
**Here is the sub classes:**
public class DesireCar1 : DesireCar
{
public override void Color()
{
Console.WriteLine("This is a red color Desire car");
}
}
public class DesireCar2 : DesireCar
{
public override void Color()
{
Console.WriteLine("This is a red white Desire car");
}
}
Beispiel einer Schnittstelle:
public interface IShape
{
// Defines the prototype(template)
void Draw();
}
// All the sub classes follow the same template but implementation can be different.
public class Circle : IShape
{
public void Draw()
{
Console.WriteLine("This is a Circle");
}
}
public class Rectangle : IShape
{
public void Draw()
{
Console.WriteLine("This is a Rectangle");
}
}
Sie können einen deutlichen Unterschied zwischen Schnittstelle und abstrakter Klasse feststellen .
Schnittstelle
Abstrakte Klasse
Die abstrakte Klasse enthält abstrakte und nicht abstrakte Methoden.
Erzwingt nicht, dass Benutzer alle Methoden implementieren, wenn die abstrakte Klasse geerbt wird.
Enthält alle Arten von Variablen, einschließlich primitiver und nicht primitiver Variablen
Mit dem abstrakten Schlüsselwort deklarieren.
Methoden und Mitglieder einer abstrakten Klasse können mit jeder Sichtbarkeit definiert werden.
Eine untergeordnete Klasse kann nur eine einzelne Klasse (abstrakt oder konkret) erweitern.
Eine abstrakte Klasse ist eine Klasse, deren Objekt nicht erstellt werden kann, oder eine Klasse, die nicht instanziiert werden kann. Eine abstrakte Methode macht eine Klasse abstrakt. Eine abstrakte Klasse muss geerbt werden, um die in der abstrakten Klasse deklarierten Methoden zu überschreiben. Keine Einschränkung für Zugriffsspezifizierer. Eine abstrakte Klasse kann Konstruktor- und andere konkrete Methoden (nicht abstrakt) enthalten, die Schnittstelle jedoch nicht.
Eine Schnittstelle ist eine Blaupause / Vorlage von Methoden (z. B. ein Haus auf einem Papier wird angegeben (Schnittstellenhaus), und verschiedene Architekten verwenden ihre Ideen, um sie zu erstellen (die Klassen von Architekten, die die Hausschnittstelle implementieren). Es handelt sich um eine Sammlung von abstrakte Methoden, Standardmethoden, statische Methoden, endgültige Variablen und verschachtelte Klassen. Alle Mitglieder sind entweder endgültige oder öffentliche, geschützte und private Zugriffsspezifizierer sind nicht zulässig. Es ist keine Objekterstellung zulässig. Eine Klasse muss erstellt werden, um die zu verwenden Eine Schnittstelle ist ein gutes Beispiel für lose Kopplung (dynamischer Polymorphismus / dynamische Bindung). Eine Schnittstelle implementiert Polymorphismus und Abstraktion. Sie gibt an, was zu tun ist, aber wie zu tun ist Implementierungsklasse. Zum Beispiel dort. 'Eine Autofirma, und sie möchte, dass einige Funktionen für alle von ihr hergestellten Autos gleich sind, damit die Firma ein Schnittstellenfahrzeug herstellt, das diese Funktionen aufweist und verschiedene Fahrzeugklassen (wie Maruti Suzkhi, Maruti 800) außer Kraft setzen diese Merkmale (Funktionen).
Warum Schnittstelle, wenn wir bereits eine abstrakte Klasse haben? Java unterstützt nur mehrstufige und hierarchische Vererbung, aber mit Hilfe der Schnittstelle können wir Mehrfachvererbung implementieren.
In praktischer Hinsicht (JAVA) besteht der Hauptunterschied zwischen abstrakter Klasse und Schnittstelle darin, dass die abstrakte Klasse den Status halten kann. Neben dem Haltezustand können wir auch mit Interface Ruhevorgänge ausführen.
In einer Schnittstelle dürfen alle Methoden nur Definitionen sein, es sollte keine einzelne implementiert werden.
Aber in einer abstrakten Klasse muss es eine abstrakte Methode mit nur Definition geben, aber andere Methoden können auch in der abstrakten Klasse mit Implementierung sein ...
Wir haben verschiedene strukturelle / syntaktische Unterschiede zwischen Schnittstelle und abstrakter Klasse. Einige weitere Unterschiede sind
[1] Szenariobasierter Unterschied :
Abstrakte Klassen werden in Szenarien verwendet, in denen wir den Benutzer darauf beschränken möchten, ein Objekt der übergeordneten Klasse zu erstellen, UND wir glauben, dass in Zukunft weitere abstrakte Methoden hinzugefügt werden.
Die Schnittstelle muss verwendet werden, wenn wir sicher sind, dass keine abstraktere Methode mehr bereitgestellt werden kann. Dann wird nur eine Schnittstelle veröffentlicht.
[2] Konzeptioneller Unterschied :
"Müssen wir in Zukunft abstraktere Methoden bereitstellen?" Wenn YES es zu einer abstrakten Klasse macht und NEIN es zu einer Schnittstelle macht.
(Am besten geeignet und gültig bis Java 1.7)
Normalerweise wird die abstrakte Klasse für den Kern von etwas verwendet, aber die Schnittstelle zum Anhängen von Peripheriegeräten.
Wenn Sie einen Basistyp für ein Fahrzeug erstellen möchten, sollten Sie eine abstrakte Klasse verwenden. Wenn Sie jedoch Funktionen oder Eigenschaften hinzufügen möchten, die nicht Teil des Basiskonzepts eines Fahrzeugs sind, sollten Sie die Schnittstelle verwenden, z. B. die Funktion "ToJSON ()" hinzufügen .
Die Schnittstelle hat eher einen breiten Abstraktionsbereich als eine abstrakte Klasse. Sie können dies an übergebenen Argumenten sehen. Sehen Sie sich dieses Beispiel an:
Wenn Sie ein Fahrzeug als Argument verwenden, können Sie nur einen der abgeleiteten Typen verwenden (Bus oder Auto - gleiche Kategorie - nur Fahrzeugkategorie). Wenn Sie jedoch die IMoveable-Schnittstelle als Argument verwenden, haben Sie mehr Auswahlmöglichkeiten.