Auf den ersten Blick scheint es, dass die Standardmethode viele neue Funktionen zum Befehlssatz der Java Virtual Machine bringt. Letztendlich können Bibliotheksentwickler die API aktualisieren, ohne dass Kompatibilitätsprobleme mit dem Client-Code auftreten. Mit Standardmethoden passt sich jede Klasse, die eine Bibliotheksschnittstelle implementiert, automatisch an die von der Schnittstelle eingeführten Standardmethoden an. Sobald der Benutzer die von ihm implementierte Klasse aktualisiert, ist es einfach, die ursprüngliche Standardmethode durch eine aussagekräftigere Methode zu überschreiben. Noch besser: Benutzer können die Standardimplementierung der Schnittstelle aufrufen und beim Überschreiben der Methode Geschäftslogik hinzufügen.
So weit, so gut. Das Hinzufügen von Standardmethoden beim Erstellen einer Schnittstelle kann jedoch dazu führen, dass Java-Code nicht kompatibel ist. Dies lässt sich anhand des folgenden Beispiels leicht verstehen. Nehmen wir an, dass eine Bibliothek eine ihrer Schnittstellen als Eingabe benötigt:
interface SimpleInput { void foo(); void bar(); } abstract class SimpleInputAdapter implements SimpleInput { @Override public void bar() { // some default behavior ... } }
Vor Java 8 war es ähnlich der oben genannten Methode zum Kombinieren einer Schnittstelle und einer Adapterklasse ein sehr verbreitetes Entwurfsmuster in der Programmiersprache Java. Dieser Adapter wird normalerweise vom Bibliotheksanbieter bereitgestellt, um Benutzern der Bibliothek bestimmte Vorgänge zu ersparen. Wenn es jedoch in Form einer Schnittstelle bereitgestellt wird, ähnelt es der Ermöglichung einer Mehrfachvererbung.
Wir gehen weiterhin davon aus, dass ein Benutzer den folgenden Adapter verwendet:
class MyInput extends SimpleInputAdapter { @Override public void foo() { // do something ... } @Override public void bar() { super.bar(); // do something additionally ... } }
Mit dieser Implementierung können wir endlich mit der Bibliothek interagieren. Beachten Sie, wie wir die bar-Methode überschreiben und der Standardimplementierung zusätzliche Funktionalität hinzufügen.
Was passiert, wenn diese Bibliothek auf Java 8 portiert wird? Erstens wird die Bibliothek höchstwahrscheinlich die Adapterklasse verwerfen und die Standardmethode verwenden, um diese Funktionalität bereitzustellen. Schließlich sieht die Schnittstelle so aus:
interface SimpleInput { void foo(); default void bar() { // some default behavior } }
Mit dieser neuen Schnittstelle kann der Benutzer seinen Code aktualisieren, um Standardmethoden anstelle der ursprünglichen Adapterklasse zu verwenden. Die letztendliche Konsequenz der Verwendung einer Schnittstelle anstelle einer Adapterklasse besteht darin, dass die Klasse andere Klassen anstelle eines bestimmten Adapters erweitern kann. Lassen Sie uns nun die MyInput-Klasse üben und transplantieren, um die Standardmethode zu verwenden. Da wir jetzt andere Klassen erweitern können, erweitern wir eine Basisklasse eines Drittanbieters. Wir müssen uns hier nicht um die Rolle dieser Basisklasse kümmern, wir können davon ausgehen, dass dies für unsere Funktion von Bedeutung ist.
class MyInput extends ThirdPartyBaseClass implements SimpleInput { @Override public void foo() { // do something ... } @Override public void bar() { SimpleInput.super.bar(); // do something additionally ... } }
Um ähnliche Funktionen wie die ursprüngliche Klasse zu erreichen, verwenden wir die neue Syntax von Java 8, um die Standardmethode der angegebenen Schnittstelle aufzurufen. Verschieben Sie gleichzeitig einen Teil der Logik unserer Methoden in die Basisklasse. An diesem Punkt klopfen Sie mir vielleicht auf die Schulter und sagen: Das ist ein sehr gutes Refactoring!
Wir haben diese Bibliothek recht erfolgreich genutzt. Allerdings müssen Betreuer eine weitere Schnittstelle hinzufügen, um mehr Funktionalität bereitzustellen. Diese Schnittstelle wird durch die ComplexInput-Schnittstelle ersetzt, die von der SimpleInput-Schnittstelle erbt und neue Methoden hinzufügt. Da das Hinzufügen von Standardmethoden im Allgemeinen sicher ist, haben die Betreuer die Standardmethode von SimpleInput überschrieben, um eine bessere Standardmethode bereitzustellen. Schließlich ist dies bei Adapterklassen üblich.
interface ComplexInput extends SimpleInput { void qux(); @Override default void bar() { SimpleInput.super.bar(); // so complex, we need to do more ... } }
Die neuen Funktionen brachten so gute Ergebnisse, dass sich auch die Leute, die ThirdPartyBaseClass verwalten, entschieden, auf diese Bibliothek zu vertrauen. Um diese Aufgabe zu erfüllen, implementiert es die ComplexInput-Schnittstelle in ThirdPartyLibrary.
Aber was bedeutet das für die MyInput-Klasse? Um die ComplexInput-Schnittstelle implizit zu implementieren, können Sie die ThirdPartyBaseClass-Klasse erben, aber der Aufruf der Standardmethode von SimpleInput wird plötzlich illegal. Infolgedessen kann der Code des Benutzers nicht kompiliert werden. Diese Art von Aufruf ist jetzt verboten, da Java es für illegal hält, die Methode der übergeordneten Klasse von einer nicht direkten Unterklasse aufzurufen. Sie können diese Standardmethode nur in ComplexInput aufrufen, dafür müssen Sie diese Schnittstelle jedoch explizit in MyInput implementieren. Für Benutzer der Bibliothek ist diese Änderung nicht zu erwarten!
Was noch seltsamer ist, ist, dass die Java-Laufzeitumgebung solche Einschränkungen nicht auferlegt. Der JVM-Validator ermöglicht es einer kompilierten Klasse, die SimpleInput::foo-Methode aufzurufen, auch wenn die Klasse die aktualisierte ThirdPartyBaseClass erbt und dadurch ComplexClass implizit implementiert. Diese Einschränkung besteht nur im Compiler.
Das obige ist der detaillierte Inhalt vonWerden die Standardmethoden von Java 8 den Benutzercode beschädigen?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!