2014-06-17 7 views
8

In Java 8 ho qualcosa di simile a questo:È possibile chiamare il metodo predefinito dell'interfaccia genitore da un'interfaccia che sottoclassi tale interfaccia?

package test; 
public class SimpleFuncInterfaceTest { 
    public static void carryOutWork(AFunctionalInterface sfi){ 
     sfi.doWork(); 
    } 
    public static void main(String[] args) { 
     carryOutWork(() -> System.out.println("Do work in lambda exp impl...")); 
     AImplementor implementsA = new AImplementor(); 
     //carryOutWork(() -> implementsA.doWork()); 
     BImplementor implementsB = new BImplementor(); 
     carryOutWork(() -> implementsB.doWork()); 
    } 
} 

@FunctionalInterface 
interface AFunctionalInterface { 
    public void doWork(); 
    default public void doSomeWork(){ 
     System.out.println("FOO"); 
    } 
} 

@FunctionalInterface 
interface BFunctionalInterface extends AFunctionalInterface { 
    @Override 
    default public void doSomeWork(){ 
     System.out.println("BAR");//Unreachable in same object? 
    } 
} 

class AImplementor implements AFunctionalInterface { 
    @Override 
    public void doWork() { 
     doSomeWork(); 
    } 
} 

class BImplementor extends AImplementor implements BFunctionalInterface { 
    public void doSomeWork(){ 
     super.doSomeWork(); 
     new BFunctionalInterface(){ 
      @Override 
      public void doWork() { 
      }}.doSomeWork(); 
      System.out.println("WUK WUK"); 
    } 
    @Override 
    public void doWork() { 
     doSomeWork(); 
    } 
} 

C'è un modo per chiamare il comportamento interfaccia funzionale di default da implementsB senza dover creare una classe interna anonima e invocando che?

Questo ha un effetto collaterale (che chiama il metodo implementsA 2 volte), che si desidera è una chiamata all'implementazione del genitore e quindi l'implementazione childs è in grado di chiamare l'implementazione predefinita del figlio, insieme a qualche specializzazione, se necessario. Come puoi vedere chiamare l'implementazione del genitore è facile, ma non vedo un modo per evitare di riscrivere l'implementazione predefinita a meno che non aggiungo un livello di riferimento indiretto alla classe che implementa l'interfaccia figlio, e non c'è modo di rafforzarlo .

Ad esempio se Un accesso sbloccato o fornito a una risorsa dice un database e B sblocca una seconda risorsa (un altro database), non vedo alcun modo per sbloccare il codice A e poi B per far rispettare questo contratto tramite l'uso di Functional Interfacce, che richiedono che A e B vengano chiamati. Un livello in profondità puoi farlo, ma i livelli N in profondità sembrano non essere possibili.

Avevo intenzione di utilizzare lambda per evitare di effettuare chiamate costose ma per imporre un ordine semantico di operazioni agli utenti della mia libreria.

Questa domanda è non è la stessa di "Chiamare esplicitamente un metodo predefinito in Java", poiché questa domanda riguarda i livelli N delle interfacce in profondità, non solo il metodo predefinito di interfacce padre.

+0

Quindi si desidera chiamare 'BFunctionalInterface.doSomeWork' da' BImplementor'? –

+1

Non è la stessa domanda di "Chiamare esplicitamente un metodo predefinito in Java", ciò richiede N livelli di profondità, mentre quella soluzione consente solo un singolo livello di riferimento indiretto. – ggb667

risposta

16

È possibile richiamare un metodo ereditato interface default utilizzando InterfaceName.super. Le regole sono le stesse delle altre chiamate al metodo super: è possibile richiamare il metodo ereditato che è stato sovrascritto, ma non è possibile richiamare direttamente il metodo che il metodo ereditato potrebbe avere sovrascritto. Per esempio.

interface A 
{ 
    void foo(); 
    default void toOverride() { 
     System.out.println("A"); 
    } 
} 
interface B extends A 
{ 
    default void toOverride() { 
     A.super.toOverride(); 
     System.out.println("B"); 
    } 
} 
interface C extends B 
{ 
    default void toOverride() { 
     A.super.toOverride();// does not work 
     B.super.toOverride(); 
     System.out.println("B"); 
    } 
} 
class D implements B 
{ 
    public void toOverride() { 

    }  
    public void foo() { 
     D.this.toOverride(); 
     B.super.toOverride(); 
     A.super.toOverride(); // does not work! 
    } 
} 

Ma se ogni metodo di sovrascrittura richiama il suo metodo super, si ha una catena di invocazioni. Tuttavia, tieni presente che stiamo parlando di interfacce. Un'implementazione può sempre sovrascrivere un metodo predefinito senza richiamare super.

Problemi correlati