Nowa funkcja dostępna w JDK 8 umożliwia dodawanie do istniejącego interfejsu przy zachowaniu zgodności binarnej.
Składnia jest podobna do
public interface SomeInterface() {
void existingInterface();
void newInterface() default SomeClass.defaultImplementation;
}
W ten sposób w przypadku wszystkich istniejących implementacji, SomeInterface
gdy aktualizują się do nowej wersji, nie wszystkie nagle mają błędy kompilacji newInterface()
.
Chociaż jest to fajne, co się dzieje, gdy wdrażasz dwa interfejsy, które dodały nową domyślną metodę, której nie zaimplementowałeś? Pozwólcie, że wyjaśnię na przykładzie.
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();
Czy zostało to już zdefiniowane jako część JDK 8?
Znalazłem bogów Jawy, którzy mówią tutaj o czymś podobnym http://cs.oswego.edu/pipermail/lambda-lib/2011-Feb February/000068.html , ale jest to część prywatnej listy mailingowej i nie mogę ich bezpośrednio zapytać.
Zobacz to, aby uzyskać więcej informacji o tym, jak wartości domyślne będą używane w JDK 8 i rozszerzaniu interfejsu Collection o obsługę lambd: https://oracleus.wingateweb.com/published/oracleus2011/sessions/25066/25066_Cho223662.pdf
Odpowiedzi:
Odpowiedź na zduplikowaną operację brzmi:
Moja odpowiedź na Twoje pytanie brzmi: Tak, jest to forma dziedziczenia wielokrotnego, ponieważ możesz dziedziczyć zachowanie po różnych rodzicach. Brakuje dziedziczenia stanów, czyli atrybutów.
źródło
Wiem, że to stary post, ale ponieważ pracuję nad tym ...
Będziesz miał błąd od kompilatora, informujący, że:
źródło
Jest ich dwóch scenariusze:
1) Po pierwsze, o czym wspomniano, gdzie nie ma konkretnego interfejsu
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) Po drugie, gdy JEST bardziej szczegółowy interfejs:
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 }
źródło
Tak, ale możesz dodać metody pobierające i ustawiające do interfejsu, które klasy implementujące muszą następnie zaimplementować. Niemniej jednak klasy implementujące nie dziedziczą atrybutów. Tak więc, AFAICS, jest to bardziej rozwiązanie w stylu cechy niż rozwiązanie w stylu wielokrotnego dziedziczenia.
źródło
Krótko mówiąc: jest to błąd czasu kompilacji, musi ręcznie przesłonić metodę w implementacji.
Cel metody domyślnej
Głównym celem wprowadzenia domyślnej metody w Javie 8 jest umożliwienie rozszerzania interfejsu bez przerywania istniejących implementacji (istnieje tak wiele bibliotek Java innych firm).
I
multiple inheritance
podobnie jak w C ++, tak naprawdę należy go unikać, zdecydowanie nie jest to celem domyślnej metody w Javie.Jak zastąpić
2 opcje:
super
, format:<interface_name>.super.<method_name>();
Porady:
public
słowa kluczowego podczas jej zastępowania.źródło
Jeśli ktoś nadal szuka odpowiedzi, w przypadku, gdy klasa implementuje dwa interfejsy z tą samą metodą domyślną, klasa musi rozwiązać tę niejednoznaczność, dostarczając własną implementację. Więcej informacji na temat dziedziczenia w metodach domyślnych można znaleźć w tym samouczku.
źródło
Pytanie „Jak rozróżnimy metody” zostało postawione na Stackoverflow i odniosło się do tego pytania konkretnych metod w interfejsach Java1.8
Oto przykład, który powinien odpowiedzieć na to pytanie:
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(); } }
Klasa C powyżej musi implementować swoją własną konkretną metodę interfejsów A i B. Mianowicie:
public void m(){ System.out.println("Interface C: m()"); }
Aby połączyć się z realizacji betonowej o sposobie ze interfejsu konkretnego , można utworzyć wystąpienia do interfejsu i jawnie wywołać w sposób konkretny tego interfejsu
Na przykład poniższy kod wywołuje konkretną implementację metody m () z interfejsu A :
new A(){}.m();
Wynik powyższego byłby:
Interfejs A: m ()
źródło
O ile mi wiadomo, nie jest to dziedziczenie wielokrotne, ponieważ są bezpaństwowcami. Dlatego wirtualne metody rozszerzające nie obsługują pełnej funkcjonalności obiektu lub klasy.
źródło