2014-06-17 27 views
8

w Java 8 mam coś takiego:Czy można wywołać domyślną metodę interfejsu nadrzędnego z interfejsu, który podklasy ten interfejs?

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

Czy istnieje sposób, aby wywołać domyślne zachowanie funkcjonalnego interfejsu od implementsB bez konieczności tworzenia anonimowej klasy wewnętrznej i powołując się, że?

To ma efekt uboczny (wywołanie metody utilsA 2 razy), pożądane jest wywołanie do implementacji rodzica, a następnie wdrożenie implementacji childs może wywołać domyślną implementację potomną, a także specjalizację w razie potrzeby. Jak widać wywołanie implementacji rodzica jest łatwe, ale nie widzę sposobu na uniknięcie ponownego zapisania domyślnej implementacji, chyba że dodaję warstwę pośrednią do klasy implementującej interfejs podrzędny, i nie ma sposobu na wymuszenie tego .

Na przykład, jeśli odblokowany lub udostępniony dostęp do zasobu mówi baza danych, a B odblokowuje drugi zasób (inna baza danych), nie widzę sposobu na odblokowanie kodu A, a następnie B wymuszenie tej umowy przy użyciu funkcji Interfejsy, wymagające wywoływania A i B. Jeden poziom głęboki możesz to zrobić, ale N poziomów głęboko wygląda tak, jak to niemożliwe.

Zamierzałem użyć lambdas, aby uniknąć kosztownych połączeń, ale wymusić semantyczną kolejność operacji na użytkownikach mojej biblioteki.

To pytanie jest nie zupełnie tak samo jak "Jawnie wywołanie metody domyślnej w Javie", ponieważ to pytanie dotyczy głębokich poziomów interfejsu N, a nie tylko wywoływania domyślnej metody interfejsu nadrzędnego.

+0

Więc chcesz wywołać 'BFunctionalInterface.doSomeWork' z' BIminstalator'? –

+1

To samo pytanie, które nie brzmi "Jawnie wywołując metodę domyślną w Javie", dotyczy około N poziomów głębi, podczas gdy to rozwiązanie pozwala tylko na jeden poziom dwukierunkowości. – ggb667

Odpowiedz

16

Możesz wywołać dziedziczoną metodę interface default, używając InterfaceName.super. Reguły są takie same, jak w przypadku innych wywołań metod super: Można wywołać dziedziczoną metodę, która została nadpisana, ale nie można bezpośrednio wywołać metody, którą metoda dziedziczona mogła zastąpić. Na przykład.

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! 
    } 
} 

Ale jeśli każda metoda nadrzędna wywołuje jej super metodę, masz łańcuch wywołań. Należy jednak pamiętać, że mówimy o interfejsach. Implementacja zawsze może zastąpić domyślną metodę bez wywoływania w ogóle wartości super.