I valori predefiniti in JDK 8 sono una forma di ereditarietà multipla in Java?

Una nuova funzionalità di JDK 8 consente di aggiungere un’interfaccia esistente preservando la compatibilità binaria.

La syntax è come

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

In questo modo per tutte le implementazioni esistenti di SomeInterface quando eseguono l’aggiornamento a questa nuova versione, non tutte hanno improvvisamente errori di compilazione attorno a newInterface() .

Mentre questo è pulito, cosa succede quando stai implementando due interfacce che hanno aggiunto un nuovo metodo predefinito che non hai implementato? Lasciatemi spiegare con un esempio.

 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(); 

È già stato definito come parte di JDK 8?

    Ho trovato gli dei Java che parlano di qualcosa di simile qui http://cs.oswego.edu/pipermail/lambda-lib/2011-February/000068.html , ma fa parte della mailing list privata e non posso chiederli direttamente.

    Vedi questo per maggiori dettagli su come i valori predefiniti verranno utilizzati in JDK 8 e l’estensione dell’interfaccia Collection per supportare lambdas: https://oracleus.wingateweb.com/published/oracleus2011/sessions/25066/25066_Cho223662.pdf

    La sessione video da guardare è qui http://medianetwork.oracle.com/video/player/1113272518001 Questo è il designer che parla della funzionalità chiamata Estensioni virtuali. Parla anche di come questo non rompa la retrocompatibilità.

    La risposta all’operazione di duplicazione è:

    Per risolvere problemi di ereditarietà, una class che implementa due interfacce che forniscono un’implementazione predefinita per lo stesso nome e firma del metodo deve fornire un’implementazione del metodo. [Articolo completo]

    La mia risposta alla tua domanda è: Sì, è una forma di ereditarietà multipla, perché puoi ereditare comportamenti da genitori diversi. Quello che manca è ereditare stati, cioè attributi.

    So che questo è un vecchio post, ma visto che sto lavorando con queste cose …

    Avrai un errore dal compilatore, che ti dice che:

     class TimeTravelingStudent eredita i valori predefiniti non correlati per presente () dai tipi. La presenza e il riferimento della linea temporale al presente è ambiguo, sia il metodo presente () nella timeline che il metodo presente () nella corrispondenza di presenze.

    La mia risposta alla tua domanda è: Sì, è una forma di ereditarietà multipla, perché puoi ereditare comportamenti da genitori diversi. Quello che manca è ereditare stati, cioè attributi.

    Sì, ma puoi aggiungere getter e setter all’interfaccia che le classi di implementazione devono implementare. Tuttavia, le classi di implementazione non ereditano gli attributi. Quindi, AFAICS, è più simile a una soluzione in stile tratto piuttosto che a una soluzione a più stili di ereditarietà.

    In breve: è un errore in fase di compilazione, deve superare il metodo manualmente nell’implementazione.


    Scopo del metodo predefinito

    Lo scopo principale di introdurre il metodo predefinito in Java 8 è quello di rendere l’interfaccia estensibile, senza interrompere le implementazioni esistenti (ci sono così tante librerie Java di terze parti).

    E multiple inheritance come in C ++ è in realtà destinata ad essere evitata, che non è sicuramente lo scopo del metodo predefinito in Java.


    Come scavalcare

    2 opzioni:

    • Sovrascrivi il metodo, con la sua logica.
    • Sovrascrivi il metodo, chiama uno dei metodi dell’interfaccia tramite super , formatta: .super.();

    Suggerimenti:

    • il metodo dall’interfaccia è di default pubblico, quindi non dimenticare di aggiungere public parola chiave public quando la sostituisci.

    Se qualcuno è ancora alla ricerca di una risposta, nel caso in cui una class implementi due interfacce con lo stesso metodo predefinito, la class deve risolvere la disambiglianza fornendo una sua implementazione. Guarda questo tutorial per maggiori dettagli su come funziona l’ereditarietà nei metodi predefiniti.

    Ci sono due scenari:

    1) Innanzitutto, è stato menzionato, in cui non esiste un’interfaccia più specifica

     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) In secondo luogo, quando c’è un’interfaccia più specifica:

      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 } 

    Per quanto vedo, non è un’eredità multipla perché sono apolidi. Quindi i metodi di estensione virtuale non supportano la piena funzionalità di oggetti o classi.