Nach meinem Verständnis müssen die in dieser Schnittstelle angegebenen Methoden von den Unterklassen verwendet werden, die diese Schnittstelle implementieren, wenn Sie eine Schnittstelle in Java implementieren.
Ich habe festgestellt, dass es in einigen Schnittstellen wie der Collection-Schnittstelle Methoden gibt, die als optional kommentiert werden. Aber was genau bedeutet das? Es hat mich ein bisschen geworfen, als ich dachte, dass alle in der Schnittstelle angegebenen Methoden erforderlich wären?
Antworten:
Die Antworten hier scheinen sehr verwirrend zu sein.
Die Java-Sprache erfordert, dass jede Methode in einer Schnittstelle von jeder Implementierung dieser Schnittstelle implementiert wird. Zeitraum. Es gibt keine Ausnahmen von dieser Regel. Zu sagen, "Sammlungen sind eine Ausnahme", deutet auf ein sehr verschwommenes Verständnis dessen hin, was hier wirklich vor sich geht.
Es ist wichtig zu wissen, dass es zwei Ebenen für die Anpassung an eine Schnittstelle gibt:
Was die Java-Sprache überprüfen kann. Das läuft so ziemlich nur darauf hinaus: Gibt es für jede der Methoden eine Implementierung?
Den Vertrag tatsächlich erfüllen. Das heißt, macht die Implementierung das, was die Dokumentation in der Benutzeroberfläche vorschreibt?
Gut geschriebene Schnittstellen enthalten eine Dokumentation, in der genau erklärt wird, was von Implementierungen erwartet wird. Ihr Compiler kann dies nicht für Sie überprüfen. Sie müssen die Dokumente lesen und das tun, was sie sagen. Wenn Sie nicht das tun, was der Vertrag vorschreibt, haben Sie eine Implementierung der Schnittstelle für den Compiler , aber es handelt sich um eine fehlerhafte / ungültige Implementierung.
Beim Entwerfen der Sammlungs-API entschied Joshua Bloch, dass er anstelle sehr feinkörniger Schnittstellen zur Unterscheidung zwischen verschiedenen Sammlungsvarianten (z. B. lesbar, beschreibbar, Direktzugriff usw.) nur sehr grobe Schnittstellen haben würde, hauptsächlich
Collection
,List
,Set
undMap
, und dann bestimmte Vorgänge als „optional“ dokumentieren. Dies sollte die kombinatorische Explosion vermeiden, die sich aus feinkörnigen Grenzflächen ergeben würde. Aus den häufig gestellten Fragen zum Java Collections API-Design :Wenn Methoden in der Collections-API als "optionale Operationen" dokumentiert sind, bedeutet dies nicht, dass Sie die Methodenimplementierung einfach in der Implementierung weglassen können, und es bedeutet auch nicht, dass Sie einen leeren Methodenkörper verwenden können (zum einen viele von ihnen sie müssen ein Ergebnis zurückgeben). Es bedeutet vielmehr, dass eine gültige Implementierungsentscheidung (eine, die noch dem Vertrag entspricht) darin besteht, eine zu werfen
UnsupportedOperationException
.Beachten Sie, dass , weil
UnsupportedOperationException
aRuntimeException
Sie es von jeder Methode Implementierung werfen können, so weit wie der Compiler geht. Zum Beispiel könnten Sie es aus einer Implementierung von werfenCollection.size()
. Eine solche Implementierung würde jedoch gegen den Vertrag verstoßen, da die Dokumentation fürCollection.size()
nicht besagt, dass dies zulässig ist.Nebenbei: Der von Javas Collections API verwendete Ansatz ist etwas umstritten (wahrscheinlich weniger als bei seiner Einführung). In einer perfekten Welt hätten Schnittstellen keine optionalen Operationen, und stattdessen würden feinkörnige Schnittstellen verwendet. Das Problem ist, dass Java weder abgeleitete Strukturtypen noch Schnittpunkttypen unterstützt, weshalb der Versuch, Dinge "richtig" zu machen, bei Sammlungen äußerst unhandlich wird.
quelle
There are no exceptions to this rule
. Ich frage mich, warum diese Antwort nicht als akzeptiert markiert ist. Andere sind gut, aber Sie haben mehr als genug gegeben.Foo
, das nichtRunnable
mit der öffentlichen Methode implementiert wirdvoid run()
. Erstellen Sie nun eine KlasseBar
, dieextends Foo
undimplements Runnable
ohne zu überschreibenrun
. Die Methode wird weiterhin implementiert, wenn auch indirekt. Ebenso ist eine Standardmethodenimplementierung immer noch eine Implementierung.remove
eine Standardimplementierung gegeben wurde. Wenn Sie es nicht implementieren, erhält Ihre Klasse die Standardimplementierung. Die beiden anderen Methoden, die Sie erwähnen, haben keine Standardimplementierungen.Um eine implementierende (nicht abstrakte) Klasse für eine Schnittstelle zu kompilieren, müssen alle Methoden implementiert werden.
Allerdings , wenn wir ein Verfahren denken, dass ihre Umsetzung ist ein einfache Ausnahme throw als ‚nicht implementiert‘ (wie einige Methoden in der
Collection
Schnittstelle), dann ist dieCollection
Schnittstelle ist die Ausnahme in diesem Fall nicht der Regelfall. Normalerweise sollte (und wird) die implementierende Klasse alle Methoden implementieren.Das "optional" in der Sammlung bedeutet, dass die implementierende Klasse es nicht "implementieren" muss (gemäß der obigen Terminologie) und es wird nur geworfen
NotSupportedException
).Ein gutes Beispiel - eine
add()
Methode für unveränderliche Sammlungen - der Beton implementiert nur eine Methode, die nur wirftNotSupportedException
In diesem Fall
Collection
wird versucht, unordentliche Vererbungsbäume zu vermeiden, die Programmierer unglücklich machen. In den meisten Fällen wird dieses Paradigma jedoch nicht empfohlen und sollte nach Möglichkeit vermieden werden.Aktualisieren:
Ab Java 8 wurde eine Standardmethode eingeführt.
Das heißt, eine Schnittstelle kann eine Methode definieren - einschließlich ihrer Implementierung.
Dies wurde hinzugefügt, um das Hinzufügen von Funktionen zu Schnittstellen zu ermöglichen und gleichzeitig die Abwärtskompatibilität für Codeteile zu unterstützen, für die die neue Funktionalität nicht erforderlich ist.
Beachten Sie, dass die Methode weiterhin von allen Klassen implementiert wird, die sie deklarieren, jedoch die Definition der Schnittstelle verwenden.
quelle
Eine Schnittstelle in Java deklariert lediglich den Vertrag für die Implementierung von Klassen. Alle Methoden in dieser Schnittstelle müssen implementiert werden, aber die implementierenden Klassen können sie nicht implementieren, dh leer lassen. Als erfundenes Beispiel
Jetzt habe ich nicht
doSomethingElse()
implementiert, so dass es für meine Unterklassen frei ist, es zu implementieren. Das ist optional.Wenn Sie jedoch über Sammlungsschnittstellen sprechen, wie andere bereits gesagt haben, sind diese eine Ausnahme. Wenn bestimmte Methoden nicht implementiert werden und Sie diese aufrufen, können sie
UnsupportedOperationException
Ausnahmen auslösen .quelle
Die optionalen Methoden in der Collection-Schnittstelle bedeuten, dass die Implementierung der Methode eine Ausnahme auslösen darf, diese jedoch trotzdem implementiert werden muss. Wie in den Dokumenten angegeben :
quelle
new Runnable ( ) { @ Override public void run ( ) { throw new UnsupportedOperationException ( ) ; } }
;add((T)null)
kann beispielsweise in einem Fall gültig sein, in einem anderen jedoch nicht . Das heißt, hier geht es um optionale Ausnahmen / Verhaltensweisen und um Argumente ("Einschränkungen für Elemente" ... "nicht förderfähiges Element" ... "als optional gekennzeichnete Ausnahmen") und nicht um optionale Methoden .Alle Methoden müssen implementiert werden, damit der Code kompiliert werden kann (mit Ausnahme derjenigen mit
default
Implementierungen in Java 8+), aber die Implementierung muss nichts funktional Nützliches tun. Insbesondere ist es:UnsupportedOperationException
(oder ähnliches) werfenDer letztere Ansatz wird häufig in den Auflistungsklassen verwendet - alle Methoden sind noch implementiert, aber einige können eine Ausnahme auslösen, wenn sie zur Laufzeit aufgerufen werden.
quelle
Tatsächlich bin ich von SurfaceView.Callback2 inspiriert. Ich denke, das ist der offizielle Weg
Wenn Ihre Klasse keine optionalen Methoden implementieren muss, implementiert sie einfach "Callback". Wenn Ihre Klasse optionale Methoden implementieren muss, implementiert sie einfach "CallbackExtended".
Entschuldigung für Scheiße Englisch.
quelle
In Java 8 und höher ist die Antwort auf diese Frage noch gültig, aber jetzt nuancierter.
Erstens bleiben diese Aussagen aus der akzeptierten Antwort richtig:
Was ist die Nuance, die in Java 8 neu ist? Wenn von "optionalen Methoden" gesprochen wird, ist jetzt eine der folgenden Optionen geeignet:
1. Eine Methode, deren Implementierung vertraglich optional ist
Die "dritte Aussage" besagt, dass abstrakte Schnittstellenmethoden immer implementiert werden müssen, und dies gilt auch für Java 8+. Wie im Java Collections Framework ist es jedoch möglich, einige abstrakte Schnittstellenmethoden im Vertrag als "optional" zu beschreiben.
In diesem Fall kann der Autor, der die Schnittstelle implementiert, festlegen, dass die Methode nicht implementiert wird. Der Compiler besteht jedoch auf einer Implementierung, und der Autor verwendet diesen Code für alle optionalen Methoden, die in der jeweiligen Implementierungsklasse nicht benötigt werden:
In Java 7 und früheren Versionen war dies wirklich die einzige Art von "optionaler Methode", die es gab, dh eine Methode, die, wenn sie nicht implementiert wurde, eine UnsupportedOperationException auslöste. Dieses Verhalten wird notwendigerweise im Schnittstellenvertrag festgelegt (z. B. die optionalen Schnittstellenmethoden des Java Collections Framework).
2. Eine Standardmethode, deren Neuimplementierung optional ist
Java 8 führte das Konzept der Standardmethoden ein . Dies sind Methoden, deren Implementierung von der Schnittstellendefinition selbst bereitgestellt werden kann und wird. Es ist im Allgemeinen nur möglich, Standardmethoden bereitzustellen, wenn der Methodenkörper mit anderen Schnittstellenmethoden (dh den "Grundelementen") geschrieben werden kann und wenn
this
"dieses Objekt, dessen Klasse diese Schnittstelle implementiert hat" bedeutet.Eine Standardmethode muss den Vertrag der Schnittstelle erfüllen (genau wie jede andere Implementierung der Schnittstellenmethode). Daher liegt es im Ermessen des Autors, eine Implementierung der Schnittstellenmethode in einer implementierenden Klasse anzugeben (sofern das Verhalten für seinen Zweck geeignet ist).
In dieser neuen Umgebung könnte das Java Collections Framework wie folgt umgeschrieben werden:
Auf diese Weise hat die "optionale" Methode
add()
das Standardverhalten, eine UnsupportedOperationException auszulösen, wenn die implementierende Klasse kein eigenes neues Verhalten bereitstellt. Dies ist genau das, was Sie sich wünschen würden und was mit dem Vertrag für List kompatibel ist. Wenn ein Autor eine Klasse schreibt, in der keine neuen Elemente zu einer List-Implementierung hinzugefügt werden können, ist die Implementierung vonadd()
optional, da das Standardverhalten genau das ist, was benötigt wird.In diesem Fall gilt die obige "dritte Aussage" weiterhin, da die Methode in der Schnittstelle selbst implementiert wurde.
3. Eine Methode, die ein
Optional
Ergebnis zurückgibtDie letzte neue Art der optionalen Methode ist einfach eine Methode, die eine zurückgibt
Optional
. DieOptional
Klasse bietet eine deutlich objektorientiertere Möglichkeit, mitnull
Ergebnissen umzugehen .In einem fließenden Programmierstil, wie er üblicherweise beim Codieren mit der neuen Java Streams-API verwendet wird, führt ein Null-Ergebnis zu jedem Zeitpunkt dazu, dass das Programm mit einer NullPointerException abstürzt. Die
Optional
Klasse bietet einen Mechanismus zum Zurückgeben von Nullergebnissen an den Clientcode auf eine Weise, die den fließenden Stil ermöglicht, ohne dass der Clientcode abstürzt.quelle
Wenn wir den Code von AbstractCollection.java in grepCode durchgehen, der eine Vorgängerklasse für alle Auflistungsimplementierungen ist, hilft dies uns, die Bedeutung optionaler Methoden zu verstehen. Hier ist der Code für die Methode add (e) in der AbstractCollection-Klasse. Methode Add (e) ist optional nach Sammlung Schnittstelle
Optionale Methode bedeutet, dass sie bereits in Vorgängerklassen implementiert ist und beim Aufruf UnsupportedOperationException auslöst. Wenn wir unsere Sammlung modifizierbar machen möchten, sollten wir die optionalen Methoden in der Sammlungsschnittstelle überschreiben .
quelle
Nun, dieses Thema wurde angesprochen an ... ja ... aber denken Sie, eine Antwort fehlt. Ich spreche über die "Standardmethoden" von Schnittstellen. Stellen Sie sich zum Beispiel vor, Sie haben eine Klasse, um etwas zu schließen (wie einen Destruktor oder so). Nehmen wir an, es sollte 3 Methoden haben. Nennen wir sie "doFirst ()", "doLast ()" und "onClose ()".
Wir möchten also, dass jedes Objekt dieses Typs zumindest "onClose ()" realisiert, die anderen sind jedoch optional.
Sie können dies anhand der "Standardmethoden" von Schnittstellen erkennen. Ich weiß, dies würde den Grund einer Schnittstelle meistens negieren, aber wenn Sie ein Framework entwerfen, kann dies nützlich sein.
Wenn Sie es also auf diese Weise realisieren möchten, sieht es wie folgt aus
Was jetzt passieren würde, wenn Sie es zum Beispiel in einer Klasse namens "Test" implementieren würden, wäre der Compiler mit den folgenden Punkten vollkommen in Ordnung:
mit dem Ausgang:
oder
mit der Ausgabe:
Alle Kombinationen sind möglich. Alles mit "Standard" kann implementiert werden, darf aber nicht, jedoch muss alles ohne implementiert werden.
Hoffe es ist nicht ganz falsch, dass ich jetzt antworte.
Ich wünsche allen einen schönen Tag!
[edit1]: Bitte beachten Sie: Dies funktioniert nur in Java 8.
quelle
Ich suchte nach einer Möglichkeit, die Rückrufschnittstelle zu implementieren, daher war die Implementierung optionaler Methoden erforderlich, da ich nicht jede Methode für jeden Rückruf implementieren wollte.
Anstatt eine Schnittstelle zu verwenden, habe ich eine Klasse mit leerer Implementierung verwendet, z.
Und Sie können die Mitgliedsvariable CallBack wie folgt festlegen:
dann nenne es so.
Auf diese Weise müssen Sie sich nicht um die Implementierung aller Methoden pro Rückruf kümmern, sondern nur die von Ihnen benötigten überschreiben.
quelle
Obwohl die Frage des OP nicht beantwortet wird, ist anzumerken, dass ab Java 8 das Hinzufügen von Standardmethoden zu Schnittstellen tatsächlich möglich ist . Das
default
Schlüsselwort in der Methodensignatur einer Schnittstelle führt dazu, dass eine Klasse die Option hat, die Methode zu überschreiben, dies jedoch nicht erfordert.quelle
Oracle Java Collections Tutorial:
quelle