Sind Standardeinstellungen in JDK 8 eine Form der Mehrfachvererbung in Java?


83

Mit einer neuen Funktion in JDK 8 können Sie eine vorhandene Schnittstelle erweitern und gleichzeitig die Binärkompatibilität beibehalten.

Die Syntax ist wie

public interface SomeInterface() {
  void existingInterface();
  void newInterface() default SomeClass.defaultImplementation;
}

Auf diese Weise SomeInterfacetreten bei allen vorhandenen Implementierungen beim Upgrade auf diese neue Version nicht alle plötzlich Kompilierungsfehler auf newInterface().

Was passiert, wenn Sie zwei Schnittstellen implementieren, die beide eine neue Standardmethode hinzugefügt haben, die Sie nicht implementiert haben? Lassen Sie mich anhand eines Beispiels erklären.

public interface Attendance {
   boolean present() default DefaultAttendance.present;
}

public interface Timeline {
   boolean present() default DefaultTimeline.present;
}

public class TimeTravelingStudent implements Attendance, Timeline {

}

// which code gets called?
new TimeTravelingStudent().present();

Wurde dies bereits als Teil von JDK 8 definiert?

Ich fand die Java-Götter, die hier über etwas Ähnliches sprachen: http://cs.oswego.edu/pipermail/lambda-lib/2011-February/000068.html , aber es ist Teil der privaten Mailingliste und ich kann sie nicht direkt fragen.

Weitere Informationen zur Verwendung der Standardeinstellungen in JDK 8 und zur Erweiterung der Collection-Oberfläche zur Unterstützung von Lambdas finden Sie hier: https://oracleus.wingateweb.com/published/oracleus2011/sessions/25066/25066_Cho223662.pdf


Die zu sehende Videositzung ist hier medianetwork.oracle.com/video/player/1113272518001 Dies ist der Designer, der über die Funktion namens Virtuelle Erweiterungen spricht. Er spricht auch darüber, wie dies die Abwärtskompatibilität nicht beeinträchtigt.
Peter Lawrey

Die Antwort auf mein Beispiel lautet also, dass Sie derzeit einen Compilerfehler erhalten. Sie sind aber offen für andere Lösungen.
Pyrolistical

Ein weiteres nützliches Material dafür ist cr.openjdk.java.net/~briangoetz/lambda/…
MohamedSanaulla

Nebenbemerkung: Die endgültige Syntax für Standardimplementierungen von Schnittstellenmethoden stellte sich als unterschiedlich heraus (Codeblock anstelle eines Verweises auf eine externe Klasse).
Joachim Sauer

4
Java hatte schon immer mehrere Vererbungen von Typen . Standardmethoden fügen eine Mehrfachvererbung des Verhaltens hinzu , jedoch nicht des Status . (Mehrfache Vererbung von Status in Sprachen wie C ++ ist der Grund für die meisten Probleme.)
Brian Goetz

Antworten:


66

Die Antwort auf die doppelte Operation lautet:

Um das Problem der Mehrfachvererbung zu lösen, muss eine Klasse, die zwei Schnittstellen implementiert, die eine Standardimplementierung für denselben Methodennamen und dieselbe Signatur bereitstellen, eine Implementierung der Methode bereitstellen. [Kompletter Artikel]

Meine Antwort auf Ihre Frage lautet: Ja, es handelt sich um eine Form der Mehrfachvererbung, da Sie Verhalten von verschiedenen Eltern erben können. Was fehlt, ist das Erben von Zuständen, dh Attributen.


2
+1: Wenn es einen Konflikt gibt, wird eine spezifischere Implementierung gegenüber einer weniger spezifischen erforderlich sein, sodass Sie angeben können, welche es sein soll, wenn es einen Konflikt gibt.
Peter Lawrey

@ H-Man2 Ich verstehe es nicht. Wenn dies zutrifft, bedeutet dies, dass die Binärkompatibilität beeinträchtigt wird. Vielleicht ist das gar nicht so schlimm, als würde man die Binärkompatibilität brechen, um Mehrfachvererbung zu verhindern.
Pyrolistical

@ PeterLawrey welches ist in meinem Beispiel spezifischer?
Pyrolistical

@Pyrolistical: Nein, die Kompatibilität wird nicht beeinträchtigt, da der Compiler die Standardimplementierung in einen normalen Methodenaufruf übersetzen kann. Ich denke, es ist eher ein Makro als eine echte Vererbung, kann aber Aspekte der Mehrfachvererbung simulieren. Vielleicht liefert das Video von Peter eine detailliertere Antwort.
H-Man2


8

Ich weiß, dass dies ein alter Beitrag ist, aber da ich mit diesem Zeug arbeite ...

Sie erhalten einen Fehler vom Compiler, der Ihnen Folgendes mitteilt:

 Die Klasse TimeTravelingStudent erbt nicht verwandte Standardeinstellungen für present () von den Typen Attendance und Timeline. Der Verweis auf present ist nicht eindeutig. Sowohl die Methode present () in der Timeline als auch die Methode present () in Attendance stimmen überein.


7

Es gibt zwei Szenarien:

1) Zunächst wurde erwähnt, dass es keine spezifischste Schnittstelle gibt

public interface A {
   default void doStuff(){ /* implementation */ }
}

public interface B {
   default void doStuff() { /* implementation */ } 
}

public class C implements A, B {
// option 1: own implementation
// OR
// option 2: use new syntax to call specific interface or face compilation error
  void doStuff(){
      B.super.doStuff();
  }
}

2) Zweitens, wenn es eine spezifischere Schnittstelle gibt:

   public interface A {
       default void doStuff() { /* implementation */ } 
    }

    public interface B extends A {
       default void doStuff() { /* implementation */ } 
    }

    public class C implements A, B {
    // will use method from B, as it is "closer" to C
    }

4

Meine Antwort auf Ihre Frage lautet: Ja, es handelt sich um eine Form der Mehrfachvererbung, da Sie Verhalten von verschiedenen Eltern erben können. Was fehlt, ist das Erben von Zuständen, dh Attributen.

Ja, aber Sie können Ihrer Schnittstelle Getter und Setter hinzufügen, die die implementierenden Klassen dann implementieren müssen. Trotzdem erben die implementierenden Klassen keine Attribute. AFAICS ähnelt also eher einer Lösung im Trait-Stil als einer Lösung im Stil der Mehrfachvererbung.


4

Kurz gesagt: Es handelt sich um einen Fehler bei der Kompilierung, der die Methode in der Implementierung manuell überschreiben muss.


Zweck der Standardmethode

Der Hauptzweck der Einführung der Standardmethode in Java 8 besteht darin, die Schnittstelle erweiterbar zu machen, ohne vorhandene Implementierungen zu beschädigen (es gibt so viele Java-Bibliotheken von Drittanbietern).

Und multiple inheritancewie in C ++ eigentlich vermieden werden soll, ist das definitiv nicht der Zweck der Standardmethode in Java.


So überschreiben Sie

2 Optionen:

  • Überschreiben Sie die Methode mit ihrer eigenen Logik.
  • Überschreiben Sie die Methode und rufen Sie eine der Methoden der Schnittstelle über das folgende superFormat auf:<interface_name>.super.<method_name>();

Tipps:

  • Die Methode von der Schnittstelle ist standardmäßig öffentlich. Vergessen Sie also nicht, publicbeim Überschreiben ein Schlüsselwort hinzuzufügen .

2

Wenn noch jemand nach einer Antwort sucht und eine Klasse zwei Schnittstellen mit derselben Standardmethode implementiert, muss die Klasse die Eindeutigkeit auflösen, indem sie eine eigene Implementierung bereitstellt. In diesem Lernprogramm finden Sie weitere Informationen zur Funktionsweise der Vererbung in Standardmethoden.


0

"Wie werden wir die Methoden unterscheiden?" War eine Frage, die auf Stackoverflow gestellt wurde und auf diese Frage konkrete Methoden in Schnittstellen Java1.8 verwies

Das folgende Beispiel sollte diese Frage beantworten:

interface A{
default public void m(){
System.out.println("Interface A: m()");
}
}

interface B{
default public void m(){
System.out.println("Interface B: m()");
}
}

 class C implements A,B { 

 public void m(){
  System.out.println("Concrete C: m()");   
 }

public static void main(String[] args) {
   C aC = new C();
   aC.m();
   new A(){}.m();
   new B(){}.m();
}
}

Die obige Klasse C muss eine eigene konkrete Methode für die Schnittstellen A und B implementieren.

 public void m(){
  System.out.println("Interface C: m()");   
 }

Um eine konkrete Implementierung einer Methode von einer bestimmten Schnittstelle aus aufzurufen , können Sie die Schnittstelle instanziieren und die konkrete Methode dieser Schnittstelle explizit aufrufen

Der folgende Code ruft beispielsweise die konkrete Implementierung der Methode m () von der Schnittstelle A auf :

new A(){}.m();

Die Ausgabe der oben genannten wäre:

Schnittstelle A: m ()


-1

Meines Erachtens handelt es sich nicht um Mehrfachvererbung, da sie zustandslos sind. Virtuelle Erweiterungsmethoden unterstützen daher nicht die vollständige Objekt- oder Klassenfunktionalität.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.