Dziedziczenie
Wywołanie innego konstruktora (this lub super) musi być pierwszą instrukcją konstruktora.
Jeśli konstruktor klasy nadrzędnej nie jest wywoływany jawnie wtedy kompilator dodaje odwołanie do bezparametrowego konstruktora klasy nadrzędnej. Jeśli klasa nadrzędna nie ma konstruktora bezparametrowego wtedy jej konstruktor parametrowy musi być wywołany przez konstruktor klasy dziedziczącej.
Konstruktor klasy nadrzędnej nie ma dostępu do metod klasy rozszerzającej (nic o niej nie wie) ale jeśli wywoła swoją metodę która jest nadpisana w klasie rozszerzającej to zostanie wywołana nadpisująca metoda. Jeśli metoda korzysta z pól, pola te będą miały wartość domyślną nawet jeśli jest ona zmieniana w konstruktorze klasy rozszerzającej (konstruktor ten będzie wywołany dopiero po utworzeniu klasy nadrzędnej).
Klasy abstrakcyjne
Klasa abstrakcyjna nie musi mieć żadnych abstrakcyjnych metod.
Metoda abstrakcyjna nie może mieć implementacji ani być prywatna.
Implementacja abstrakcyjnych metod podlega tym samym zasadom co nadpisywanie.
Nadpisywanie
Żeby nadpisanie miało miejsce muszą być spełnione warunki:
- sygnatury metod muszą być takie same
- metoda nadpisująca musi być co najmniej tak samo dostępna
- metoda nadpisująca nie może rzucać ogólniejszego lub nowego sprawdzanego wyjątku (może precyzować)
- jeśli metoda nadpisująca coś zwraca, typ zwracany musi być ten sam lub bardziej szczegółowy (kowariantny – nie dotyczy typów prostych)
Prywatne metody nie są nadpisywane ale mogą być deklarowane metody o tej samej sygnaturze które nie mają związku z metodą klasy bazowej.
Przy nadpisywaniu referencja nie ma znaczenia, istotny jest tylko rzeczywisty typ obiektu (który jest sprawdzany w czasie uruchomienia).
Przesłanianie
Metody statyczne mogą być przesłaniane (poza finalnymi). Warunki dla przesłaniania są takie same jak dla nadpisywania oraz metoda przesłaniana oraz przesłaniająca muszą być statyczne (inaczej występuje błąd kompilacji).
Zmienne statyczne mogą być przesłaniane przez niestatyczne i odwrotnie.
Przesłoniętą metodę można wywołać przez super.metoda() lub rzutowanie, analogicznie dla zmiennych.
Przy przesłanianiu referencja decyduje która metoda będzie wywołana (dzieje się to w czasie kompilacji).
Przeciążanie
Nie można przeciążać po typie zwracanym.
Interfejsy
Interfejsy domyślnie mają modyfikator abstract
, dozwolony dostęp publiczny lub pakietowy.
Pola domyślnie mają modyfikatory public static final
.
Do pól można odwołać się przez nazwę interfejsu, nazwę klasy która go implementuje lub referencje do niej a wewnątrz klasy która go implementuje także bez żadnej referencji (przez this
).
Metody domyślnie mają modyfikatory public abstract
.
Metody interfejsu tak jak metody abstrakcyjny nie mogą być private
, protected
ani final
.
Jeśli wiele implementowanych interfejsów ma metodę o tej samej sygnaturze to wystarczy ją zaimplementować raz.
Jeśli metody w dwóch interfejsach mają te same sygnatury ale różne typy zwracane – nie mogą być implementowane jednocześnie.
Metody domyślne interfejsów nie mogą być statyczne, ale można mieć metodę domyślną w interfejsie dziedziczącym o takiej samej sygnaturze jak metoda statyczna w metodzie bazowej (odwrotnie jest błąd kompilacji).
SuperInterface.super.method()
wywołuje metodę domyślną z rozszerzanego interfejsu, można przejść tylko jeden poziom do góry.
Samo super
się nie skompiluje ponieważ interfejs może rozszerzać kilka interfejsów.
Można nadpisywać metody domyślne (rozszerzając interfejs z metodą domyślną).
Metody domyślne umożliwiają wielokrotne dziedziczenie. Jeśli nie jest jasne która metoda powinna być wywołana występuje błąd kompilacji, chyba że klasa sama nadpisuje metodę która jest dziedziczona domyślnie z kilku interfejsów.
Interfejsy mogą mieć metody statyczne ale te metody nie są dziedziczone przez klasy implementujące interfejs (nie można się do nich odwołać też przez referencje do interfejsu). Dzięki temu nie ma wielokrotnego dziedziczenia (konieczność jawnego napisania o metodę z którego interfejsu chodzi).
Jeśli interfejs ma metodę która także jest w klasie rozszerzanej ale o mniejszym dostępie. Klasa która implementuje i rozszerza jednocześnie musi przesłonić metodę żeby zwiększyć jej poziom dostępu.
Istnienie pól lub metod o jednakowych sygnaturach w interfejsach implementowanych przez jedną klasę nie generuje błędu. Dopiero niejednoznaczne odwołanie (bez podania konkretnego interfejsu) generuje błąd kompilacji.
Źródła:
„OCA: Oracle Certified Associate Java SE 8 Programmer I Study Guide: Exam 1Z0-808” Jeanne Boyarsky, Scott Selikoff
„JA+ V8 for Oracle Certified Associate – Java SE8 Programmer I” http://enthuware.com