Java 8 ermöglicht die Standardimplementierung von Methoden in Schnittstellen, die als Standardmethoden bezeichnet werden .
Ich bin verwirrt darüber, wann ich diese Art von interface default method
anstelle von abstract class
(mit abstract method(s)
) verwenden würde.
Wann sollte eine Schnittstelle mit Standardmethoden verwendet werden und wann sollte eine abstrakte Klasse (mit abstrakten Methoden) verwendet werden? Sind die abstrakten Klassen in diesem Szenario noch nützlich?
java
interface
java-8
abstract-class
default-method
Narendra Pathai
quelle
quelle
Antworten:
Abstrakte Klassen bieten viel mehr als Standardmethodenimplementierungen (z. B. privater Status). Ab Java 8 sollten Sie jedoch immer dann, wenn Sie die Wahl haben, die Defender-
default
Methode (auch bekannt als. ) In der Benutzeroberfläche verwenden.Die Einschränkung für die Standardmethode besteht darin, dass sie nur in Form von Aufrufen anderer Schnittstellenmethoden implementiert werden kann, ohne dass auf den Status einer bestimmten Implementierung Bezug genommen wird. Der Hauptanwendungsfall sind also übergeordnete und bequeme Methoden.
Das Gute an dieser neuen Funktion ist, dass Sie, bevor Sie zuvor gezwungen waren, eine abstrakte Klasse für die Convenience-Methoden zu verwenden, wodurch der Implementierer auf eine einzelne Vererbung beschränkt wurde, jetzt ein wirklich sauberes Design mit nur der Schnittstelle und einem Minimum an Implementierung haben können Anstrengung dem Programmierer aufgezwungen.
Die ursprüngliche Motivation,
default
Methoden in Java 8 einzuführen , war der Wunsch, die Collections Framework-Schnittstellen mit Lambda-orientierten Methoden zu erweitern, ohne vorhandene Implementierungen zu beschädigen. Obwohl dies für die Autoren öffentlicher Bibliotheken relevanter ist, finden Sie dieselbe Funktion möglicherweise auch in Ihrem Projekt nützlich. Sie haben einen zentralen Ort, an dem Sie neuen Komfort hinzufügen können, und Sie müssen sich nicht darauf verlassen, wie der Rest der Typhierarchie aussieht.quelle
Es gibt einige technische Unterschiede. Abstrakte Klassen können im Vergleich zu Java 8-Schnittstellen noch mehr:
Konzeptionell besteht der Hauptzweck von Defender-Methoden in der Abwärtskompatibilität nach Einführung neuer Funktionen (als Lambda-Funktionen) in Java 8.
quelle
public static final
Felder einer Schnittstelle nicht als "Zustand" beschreiben. Derstatic
Teil bedeutet, dass sie überhaupt nicht auf eine bestimmte Instanz bezogen sind. Sie werden bei der Klasseninstanziierung zugewiesen , was nicht mit der nach der Instanzerstellung identisch ist .Dies wird in diesem Artikel beschrieben . Denken Sie
forEach
an Sammlungen.quelle
AbstractList::forEach
werfenUnsupportedOperationException
.Diese beiden sind sehr unterschiedlich:
Standardmethoden sind das Hinzufügen externer Funktionen zu vorhandenen Klassen, ohne deren Status zu ändern.
Und abstrakte Klassen sind eine normale Art der Vererbung, sie sind normale Klassen, die erweitert werden sollen.
quelle
Wie in diesem Artikel beschrieben,
Abstrakte Klassen versus Schnittstellen in Java 8
quelle
In Bezug auf Ihre Anfrage von
Java- Dokumentation bietet perfekte Antwort.
Abstrakte Klassen im Vergleich zu Schnittstellen:
Anwendungsfälle für jeden von ihnen wurden im folgenden SE-Beitrag erläutert:
Was ist der Unterschied zwischen einer Schnittstelle und einer abstrakten Klasse?
Ja. Sie sind immer noch nützlich. Sie können nicht statische, nicht endgültige Methoden und Attribute enthalten ( geschützt, privat zusätzlich zu öffentlich ), was selbst mit Java-8-Schnittstellen nicht möglich ist.
quelle
Wann immer wir die Wahl zwischen abstrakter Klasse und Schnittstelle haben, sollten wir immer (fast) Standardmethoden (auch als Defender- oder virtuelle Erweiterungen bezeichnet) bevorzugen.
Collection and AbstractCollection
. Jetzt sollten wir die Methoden in der Schnittstelle selbst implementieren, um die Standardfunktionalität bereitzustellen. Die Klassen, die die Schnittstelle implementieren, haben die Wahl, die Methoden zu überschreiben oder die Standardimplementierung zu erben.Eine weitere wichtige Verwendung von Standardmethoden ist
interface evolution
. Angenommen, ich hätte einen Klassenball als:public class Ball implements Collection { ... }
Jetzt wird in Java 8 eine neue Funktion eingeführt. Wir können einen Stream erhalten, indem wir eine
stream
Methode verwenden, die der Schnittstelle hinzugefügt wurde. Wenn diesstream
keine StandardmethodeCollection
wäre, wären alle Implementierungen für die Schnittstelle fehlerhaft, da sie diese neue Methode nicht implementieren würden. Das Hinzufügen einer nicht standardmäßigen Methode zu einer Schnittstelle ist dies nichtsource-compatible
.Angenommen, wir kompilieren die Klasse nicht neu und verwenden eine alte JAR-Datei, die diese Klasse enthält
Ball
. Die Klasse wird ohne diese fehlende Methode einwandfrei geladen, Instanzen können erstellt werden und anscheinend funktioniert alles einwandfrei. ABER wenn das Programm diestream
Methode auf eine Instanz von aufruft , erhaltenBall
wirAbstractMethodError
. Die Standardeinstellung der Methode löste also beide Probleme.quelle
Standardmethoden in der Java-Schnittstelle ermöglichen die Entwicklung der Schnittstelle .
Wenn Sie bei einer vorhandenen Schnittstelle eine Methode hinzufügen möchten, ohne die Binärkompatibilität mit älteren Versionen der Schnittstelle zu beeinträchtigen, stehen Ihnen zwei Optionen zur Verfügung: Hinzufügen einer Standardmethode oder einer statischen Methode. In der Tat müsste jede abstrakte Methode, die der Schnittstelle hinzugefügt wird, von den Klassen oder Schnittstellen implementiert werden, die diese Schnittstelle implementieren.
Eine statische Methode ist für eine Klasse eindeutig. Eine Standardmethode ist für eine Instanz der Klasse eindeutig.
Wenn Sie einer vorhandenen Schnittstelle eine Standardmethode hinzufügen, müssen Klassen und Schnittstellen, die diese Schnittstelle implementieren, diese nicht implementieren. Sie können
Mehr zum Thema hier .
quelle
Obwohl es eine alte Frage ist, möchte ich auch meinen Beitrag dazu leisten.
abstrakte Klasse: Innerhalb der abstrakten Klasse können wir Instanzvariablen deklarieren, die für die untergeordnete Klasse erforderlich sind
Schnittstelle: Innerhalb der Schnittstelle sind alle Variablen immer öffentlich statisch und endgültig. Wir können keine Instanzvariablen deklarieren
abstrakte Klasse: Die abstrakte Klasse kann über den Zustand des Objekts sprechen
Schnittstelle: Die Schnittstelle kann niemals über den Zustand des Objekts sprechen
abstrakte Klasse: Innerhalb der abstrakten Klasse können wir Konstruktoren deklarieren
Schnittstelle: Innerhalb der Schnittstelle können wir keine Konstruktoren deklarieren, da der Zweck von
Konstruktoren darin besteht, Instanzvariablen zu initialisieren. Also , was ist die Notwendigkeit des Konstruktor da , wenn wir keine Instanzvariablen in Schnittstellen haben .
abstrakte Klasse: Innerhalb der abstrakten Klasse können wir Instanz- und statische Blöcke deklarieren
Schnittstelle: Schnittstellen dürfen keine Instanz- und statischen Blöcke enthalten.
abstrakte Klasse: Die abstrakte Klasse kann keinen Lambda-Ausdruck referenzieren
Schnittstellen: Schnittstellen mit einer einzelnen abstrakten Methode können auf Lambda-Ausdrücke verweisen
abstrakte Klasse : Innerhalb der abstrakten Klasse können wir OBJECT CLASS-Methoden überschreiben
Schnittstellen: Wir können OBJECT CLASS-Methoden innerhalb von Schnittstellen nicht überschreiben.
Ich werde mit dem Hinweis enden, dass:
Standardmethodenkonzepte / statische Methodenkonzepte in der Schnittstelle dienten nur dazu, Implementierungsklassen zu speichern, aber keine sinnvolle nützliche Implementierung bereitzustellen. Standardmethoden / statische Methoden sind eine Art Dummy-Implementierung. "Wenn Sie möchten, können Sie sie verwenden oder überschreiben (bei Standardmethoden) in der Implementierungsklasse." Dies erspart uns die Implementierung neuer Methoden in Implementierungsklassen, wenn neue Methoden in Schnittstellen verwendet werden sind hinzugefügt. Daher können Schnittstellen niemals abstrakten Klassen entsprechen.
quelle
Die Remi Forax- Regel lautet: Sie entwerfen nicht mit abstrakten Klassen. Sie gestalten Ihre App mit Schnittstellen . Was auch immer die Version von Java ist, was auch immer die Sprache ist. Es wird von dem gesicherten I nterface Segregation Prinzip in SOL I D Prinzipien.
Sie können später abstrakte Klassen verwenden, um Code zu faktorisieren. Mit Java 8 können Sie dies jetzt direkt in der Benutzeroberfläche tun. Dies ist eine Einrichtung, nicht mehr.
quelle
Abwärtskompatibilität: Stellen Sie sich vor, Ihre Schnittstelle wird von Hunderten von Klassen implementiert. Wenn Sie diese Schnittstelle ändern, werden alle Benutzer gezwungen, die neu hinzugefügte Methode zu implementieren, obwohl dies für viele andere Klassen, die Ihre Schnittstelle implementieren, möglicherweise nicht unbedingt erforderlich ist. Außerdem ermöglicht es Ihre Schnittstelle eine funktionale Schnittstelle sein
Fakten & Einschränkungen:
1-Darf nur innerhalb einer Schnittstelle und nicht innerhalb einer Klasse oder abstrakten Klasse deklariert werden.
2-Muss einen Körper bereitstellen
3-Es wird nicht angenommen, dass es abstrakt ist wie andere normale Methoden, die in einer Schnittstelle verwendet werden.
quelle
In Java 8 sieht eine Schnittstelle wie eine abstrakte Klasse aus, obwohl es einige Unterschiede geben kann, wie z.
1) Abstrakte Klassen sind Klassen, daher sind sie nicht auf andere Einschränkungen der Schnittstelle in Java beschränkt, z. B. können abstrakte Klassen den Status haben , aber Sie können den Status auf der Schnittstelle in Java nicht haben.
2) Ein weiterer semantischer Unterschied zwischen der Schnittstelle mit Standardmethoden und der abstrakten Klasse besteht darin, dass Sie Konstruktoren innerhalb einer abstrakten Klasse definieren können, aber keinen Konstruktor innerhalb der Schnittstelle in Java definieren können
quelle
Standardmethoden in der Java-Schnittstelle sollen eher zur Bereitstellung einer Dummy-Implementierung einer Funktion verwendet werden, wodurch jede implementierende Klasse dieser Schnittstelle vor dem Problem bewahrt wird, alle abstrakten Methoden zu deklarieren, selbst wenn sie nur eine behandeln möchten. Standardmethoden in der Schnittstelle sind somit eher ein Ersatz für das Konzept der Adapterklassen.
Die Methoden in der abstrakten Klasse sollen jedoch eine sinnvolle Implementierung liefern, die jede untergeordnete Klasse nur überschreiben sollte, wenn dies zum Überschreiben einer gemeinsamen Funktionalität erforderlich ist.
quelle
Wie in anderen Antworten erwähnt, wurde die Möglichkeit hinzugefügt, einer Schnittstelle eine Implementierung hinzuzufügen, um die Abwärtskompatibilität im Collections-Framework zu gewährleisten. Ich würde argumentieren, dass die Bereitstellung von Abwärtskompatibilität möglicherweise der einzige gute Grund ist, einer Schnittstelle eine Implementierung hinzuzufügen.
Wenn Sie andernfalls einer Schnittstelle eine Implementierung hinzufügen, verstoßen Sie gegen das Grundgesetz, warum Schnittstellen überhaupt hinzugefügt wurden.Java ist im Gegensatz zu C ++ eine einzelne Vererbungssprache, die eine Mehrfachvererbung ermöglicht. Schnittstellen bieten die Tippvorteile einer Sprache, die Mehrfachvererbung unterstützt, ohne die Probleme einzuführen, die mit Mehrfachvererbung verbunden sind.
Insbesondere erlaubt Java nur die einmalige Vererbung einer Implementierung, jedoch die mehrfache Vererbung von Schnittstellen. Folgendes ist beispielsweise gültiger Java-Code:
MyObject
erbt nur eine Implementierung, aber drei Verträge.Java hat die Mehrfachvererbung der Implementierung weitergegeben, da die Mehrfachvererbung der Implementierung mit einer Vielzahl heikler Probleme verbunden ist, die außerhalb des Rahmens dieser Antwort liegen. Schnittstellen wurden hinzugefügt, um die Mehrfachvererbung von Verträgen (auch als Schnittstellen bezeichnet) ohne die Probleme der Mehrfachvererbung der Implementierung zu ermöglichen.
Um meinen Standpunkt zu unterstützen, hier ein Zitat von Ken Arnold und James Gosling aus dem Buch The Java Programming Language, 4. Auflage :
quelle
Bitte denken Sie zuerst an das offene / geschlossene Prinzip. Die Standardmethoden in Schnittstellen VERLETZEN es. Dies ist eine schlechte Funktion in Java. Es fördert schlechtes Design, schlechte Architektur und niedrige Softwarequalität. Ich würde vorschlagen, die Verwendung von Standardmethoden vollständig zu vermeiden.
Stellen Sie sich ein paar Fragen: Warum können Sie Ihre Methoden nicht in die abstrakte Klasse einordnen? Benötigen Sie dann mehr als eine abstrakte Klasse? Denken Sie dann darüber nach, wofür Ihre Klasse verantwortlich ist. Sind Sie sicher, dass alle Methoden, die Sie der einzelnen Klasse zuordnen, wirklich denselben Zweck erfüllen? Möglicherweise unterscheiden Sie mehrere Zwecke und teilen Ihre Klasse dann in mehrere Klassen auf, für jeden Zweck eine eigene Klasse.
quelle