2016-05-12 13 views
6

Powiedzmy, istnieją następujące typy:Java 8 domyślna metoda dziedziczenie

public interface Base { 

    default void sayHi(){ 
     System.out.println("hi from base"); 
    } 
} 

public interface Foo extends Base { 
    @Override 
    default void sayHi(){ 
     System.out.println("hi from foo"); 
    } 
} 

public interface Bar extends Base { 
} 

public class MyClass implements Foo, Bar { 
    public static void main(String[] args) { 
     MyClass c = new MyClass(); 
     c.sayHi(); 
    } 
} 

W tym scenariuszu, jeśli main jest wykonywany, „cześć z foo” jest drukowana. Dlaczego implementacja Foo ma pierwszeństwo? Czy Bar nie dziedziczy sayHi() od Base, ponieważ jeśli MyClass miałaby zaimplementować tylko Bar, implementacja Base byłaby wywoływana? Więc sensowne byłoby, aby kod nadal się nie kompilował. Ponadto, ponieważ Bar powinien mieć wdrożenie Base „s sayHi(), dlaczego nie mogę zastąpić go MyClass jak:

@Override 
public void sayHi() { 
    Bar.super.sayHi(); 
} 

następujący błąd występuje, gdy próbuje zrobić:

zły typ kwalifikatora Bar w domyślnej metodzie super-wywołania, sayHi() jest nadpisywane w Foo

+0

@Casey Z jakiego IDE korzystasz? Eclipse daje kolejny błąd. –

+0

@JornVernee To było z IntelliJ. Jakie są wyniki Eclipse? – Casey

+0

@ Casey '' 'Niedozwolone odwołanie do super metody sayHi() z typu Base, nie można pominąć bardziej konkretnego zastąpienia typu Foo' '' –

Odpowiedz

9

To zachowanie jest określone przy użyciu prawie twojego dokładnego przykładu w JLS 9.4.1, po prostu wi th niektóre nazwy zmieniły się wokół:

interface Top { 
    default String name() { return "unnamed"; } 
} 
interface Left extends Top { 
    default String name() { return getClass().getName(); } 
} 
interface Right extends Top {} 

interface Bottom extends Left, Right {} 

Prawy dziedziczy nazwę() od góry, ale dno nazwę inherits (od lewej), nie w porządku. Dzieje się tak, ponieważ name() from Left zastępuje deklarację nazwy() w górnej.

JLS wydaje się nie dawać szczególnie konkretnego powodu, który widzę; tak właśnie działali projektanci Javy, którzy zdecydowali się na dziedziczenie.

+0

Ma sens. Rodzaj wydaje się jak wada projektu. Zastąpienie domyślnej metody na zawsze ukrywa oryginalną implementację, która w złożonej hierarchii może być krytyczna. Wygląda na to, że pozwolenie konkretnej klasie zdecydować, która implementacja będzie lepszym rozwiązaniem. – aiguy

+3

@aiguy to ... rodzaj przesady. I tak było w przypadku normalnego dziedziczenia klasowego, że nadpisanie całkowicie ukrywa implementację supertypów. –

+0

cóż, w normalnym dziedziczeniu klas nigdy nie można mieć 2 implementacji nadrzędnych. Chodzi mi o to, że jeśli w złożonej hierarchii ktoś doda przesłonięcie pierwotnej domyślnej implementacji, może złamać całą hierarchię, jeśli niektóre konkretne klasy polegają na oryginalnej implementacji. – aiguy

9

Jest to zgodne z projektem. Od JLS 15.12.3:

Jeśli formularz jest TypeName. Wspaniały . [TypeArguments] identyfikator, a następnie:

  • Jeśli TypeName oznacza interfejs przez T jest zgłoszenie typu natychmiast zamykający metody przywołanie. Błąd w czasie kompilacji, jeśli istnieje sposób odmienny od zgłoszenia kompilacji, który zastępuje (§9.4.1) zgłoszenie kompilacji z bezpośredniego nadrzędnej lub bezpośrednie superinterface T.

W przypadku że superinterfejs zastępuje metodę zadeklarowaną w interfejsie typu grandparent, ta reguła uniemożliwia dziecięcemu interfejsowi "pomijanie" nadpisania przez proste dodanie elementu nadrzędnego do listy bezpośrednich superinterfejsów. Odpowiedni sposób dostępu do funkcji urządzenia typu grandparent polega na bezpośrednim interfejsie nadrzędnym i tylko wtedy, gdy ten interfejs wybierze odsłonięcie pożądanego zachowania. (Alternatywnie programista może zdefiniować własną dodatkową superinterfejs, która ujawnia pożądane zachowanie za pomocą wywołania super metody.)

+0

Pomiędzy tą a [inną odpowiedzią] (http://stackoverflow.com/a/37197609/5221149), odpowiedź na pytanie została w pełni rozwiązana. Teraz, która odpowiedź zostanie zaakceptowana? Hmmm.... – Andreas

Powiązane problemy