W Javie 8 wprowadzono pojęcie default methods — to metody z implementacją, zadeklarowane wewnątrz interfejsu. Pozwalają one na dodawanie nowych metod do interfejsów, nie naruszając zgodności z istniejącymi implementacjami.
Składnia:
public interface MyInterface { default void printHello() { System.out.println("Hello!"); } }
Cechy i subtelności:
Object (np. equals, hashCode).Co się stanie, jeśli klasa implementuje dwa interfejsy z identyczną metodą default i nie nadpisuje tej metody?
Odpowiedź: Kompilator zgłosi błąd "class... inherits unrelated defaults for ... from types ... and ...", i konieczne będzie jawne zaimplementowanie tej metody w klasie.
Przykład:
interface A { default void doSomething() { System.out.println("A"); } } interface B { default void doSomething() { System.out.println("B"); } } class C implements A, B {} // Błąd kompilacji!
Rozwiązanie:
class C implements A, B { @Override public void doSomething() { A.super.doSomething(); // lub B.super.doSomething() } }
Historia
W projekcie zespołowym do migracji API dodano metodę default do wspólnego interfejsu. Stare implementacje interfejsu nie nadpisały nowej metody, co doprowadziło do nieoczekiwanego zachowania, ponieważ wykonywana była domyślna implementacja zamiast oczekiwanej logiki. W rezultacie użytkownicy zauważyli spadek funkcjonalności.
Historia
Przy rozszerzaniu biblioteki jeden z programistów dodał metodę default z logiką biznesową do wspólnego interfejsu. Następne dodanie takiej samej metody z innym zachowaniem do innego interfejsu spowodowało konflikt dziedziczenia, co uniemożliwiło skompilowanie nowych implementacji.
Historia
Programista próbował użyć metody default o nazwie
hashCodew interfejsie, oczekując, że wpłynie to na nadpisanie metody w klasach dziedziczących, ale kompilator na to nie pozwolił. Doprowadziło to do długiego wyjaśniania przyczyn błędu i przemyślenia struktury interfejsów.