2016-12-21 2 views
3

Problem:Java 8 bieten nicht die gleiche Lösung Mehrfachvererbung zu ermöglichen, die sie gaben Schnittstelle Standardmethoden zu lösen

Wir wissen, dass Java nicht erlaubt mehrere Klassen zu erweitern, weil es in der Folge hätte Diamond Problem wo der Compiler konnte nicht entscheiden, welche Superklasse-Methode zu verwenden. Mit Standard-Methoden der Schnittstelle Diamond Problem wurden Einführung in Java 8. Das heißt, wenn eine Klasse zwei Schnittstellen implementiert, von denen jede die gleiche Standardmethode definiert und die implementierende Klasse die allgemeine Standardmethode nicht überschreibt, kann der Compiler nicht entscheiden, welche Implementierung ausgewählt werden soll.

Lösung:

Java 8 erfordert eine Implementierung für Standardmethoden um mehr als eine Schnittstelle implementiert zur Verfügung zu stellen. Wenn also eine Klasse beide oben genannten Schnittstellen implementieren würde, müsste sie eine Implementierung für die gemeinsame Standardmethode bereitstellen. Andernfalls würde der Compiler einen Kompilierzeitfehler ausgeben.

Frage:

Warum ist diese Lösung nicht für mehrere Klassenvererbung, durch gemeinsame Methoden überschreiben von Kind Klasse eingeführt?

Antwort

0

Methoden, die von Schnittstellen eingeführt werden, können immer überschrieben werden, während Methoden, die von Klassen eingeführt werden, endgültig sein können. Dies ist ein Grund, warum Sie möglicherweise nicht die gleiche Strategie für Klassen anwenden können wie für Schnittstellen.

5

Sie haben das Diamond-Problem nicht richtig verstanden (und vorausgesetzt, der aktuelle Stand des Wikipedia-Artikels erklärt es nicht ausreichend). Wie in dieser Grafik gezeigt,

A true diamond

der Diamanten Problem tritt auf, wenn die gleiche Klasse mehrfach durch verschiedene Vererbungsweg vererbt. Dies ist kein Problem für Schnittstellen (und war es nie), da sie nur einen Vertrag definieren und denselben Vertrag mehrere Male angeben, macht keinen Unterschied.

Das Hauptproblem ist nicht mit den Methoden, sondern die Daten dieser Super-Typ zugeordnet. Sollte der Instanzstatus A in diesem Fall ein- oder zweimal vorhanden sein? Wenn einmal, können C und B unterschiedliche, widersprüchliche Einschränkungen für den Instanzstatus A haben. Beide Klassen können auch annehmen, dass sie die volle Kontrolle über den Zustand von A haben, d. H. Nicht berücksichtigen, dass andere Klassen die gleiche Zugriffsstufe haben. Wenn zwei verschiedene A Zustände vorliegen, wird eine Erweiterung der Umwandlung einer Referenz zu einer A Referenz mehrdeutig, da entweder A gemeint sein könnte.

Schnittstellen haben diese Probleme nicht, da sie keine Instanzdaten enthalten. Sie haben auch (fast) keine Zugänglichkeitsprobleme, da ihre Methoden immer public sind. Das Zulassen von default Methoden ändert das nicht, da default Methoden immer noch nicht auf Instanzvariablen zugreifen, sondern nur mit den Schnittstellenmethoden arbeiten.

Natürlich gibt es die Möglichkeit, dass B und Cdefault Methoden mit identischer Unterschrift erklärten, eine Mehrdeutigkeit zu verursachen, die in D gelöst werden muss. Dies ist jedoch sogar der Fall, wenn es keine A gibt, d. H. Überhaupt keinen "Diamanten". Dieses Szenario ist also kein korrektes Beispiel für das "Diamond Problem".

+0

Ich stimme dem Argument von Shared State für das Diamantproblem zu, aber wenn Sie Unterstützung für die Mehrfachvererbung in * Java * hätten, müssten Sie sich mit dem Problem befassen, eine der mehreren Implementierungen eines einzigen zu wählen Methode. Dieses Problem wird in der Frage und wie es für Schnittstellen in Java 8 gelöst wird angegeben. Die gleiche Lösung konnte nicht garantiert für Klassen angewendet werden. Oder habe ich etwas verpasst? – Harmlezz

+2

@Harmlezz: Wie im letzten Absatz erwähnt, ist das Problem der Unterscheidung zwischen mehreren geerbten Nicht-'Abstrakt'-Methoden ein Problem der Mehrfachvererbung im Allgemeinen, aber es erfordert keinen gemeinsamen Super-Typ, um zu zeigen , hat nichts mit dem * Diamond * -Problem zu tun. Sie haben Recht, dass dies ein Problem ist, das nicht generell für Nicht-Interface-Klassen auf die gleiche Weise gelöst werden kann, aber dennoch ist es nicht das spezielle Problem, das "Diamond Problem" genannt wird. – Holger

0

Der Konflikt als „Diamant-Problem“ am besten dargestellt werden kann, einen polymorphen Aufruf der Methode unter Verwendung von A.m() wo der Laufzeittyp des Empfängers D Typen hat: Stellen Sie sich vor D erbt zwei verschiedene Methoden beide behaupten, die Rolle des A.m() (ein spielen von ihnen könnte die ursprüngliche Methode sein A.m(), mindestens eine von ihnen ist eine Überschreibung). Jetzt kann die dynamische Verteilung nicht entscheiden, welche der widersprüchlichen Methoden aufgerufen werden soll.

Abgesehen: der Unterschied zwische das „Diamant-Problem“ und regelmäßige Namenskonflikte ist besonders relevant in Sprachen wie Eiffel, wo der Konflikt lokal aufgelöst für die Perspektive des Typs durch Umbenennen eine Methode D, zum Beispiel sein könnte. Dies würde den Namenskonflikt für Aufrufe mit dem statischen Typ vermeiden, jedoch nicht für Aufrufe mit dem statischen Typ A.

nun mit Standardmethoden in Java 8 wurde JLS mit Regeln geändert, dass solche Konflikte erkennen, erfordern D den Konflikt (viele verschiedene Fälle existieren, je nachdem, ob nicht einige der Arten beteiligt sind Klassen) zu lösen . Das heißt, das Diamantproblem wird in Java 8 nicht "gelöst", es wird nur vermieden, indem irgendwelche Programme abgelehnt werden, die es erzeugen würden.

In der Theorie konnten ähnliche Regeln in Java 1 definiert werden, um Mehrfachvererbung für Klassen zuzulassen. Es ist nur eine Entscheidung, die schon früh getroffen wurde, dass die Entwickler von Java nicht wollten, um mehrfache Vererbung zu unterstützen.

Die Wahl, mehrfache (Implementierungs-) Vererbung für Standardmethoden, aber nicht für Klassenmethoden zuzulassen, ist eine rein pragmatische Wahl, die von keiner Theorie benötigt wird.

Verwandte Themen