W poprzednim rozdziale omawialiśmy dziedziczenie i przedstawiliśmy tam jego najważniejsze aspekty. Nie oznacza to jednak, że temat został przez nas wyczerpany.
Przesłanianie metod to kontynuacja tego zagadnienia i tym zajmiemy się już za chwilę. Najpierw jednak wprowadzimy mały suplement do samego dziedziczenia, tak
aby używane przez nas słownictwo było zawsze zrozumiałe.
Zarówno klasa dziedzicząca, jak i klasa, z której dziedziczymy, bardzo często określane są różnymi nazwami i sami przyznajemy, że można się w tym
nazewnictwie nieco pogubić. Postanowiliśmy więc przytoczyć wszystkie znane nam określenia dla tych klas.
Postaramy się nie nadużywać różnorodności tych konstrukcji. Zawsze najbardziej podobały się nam określenia
klasa bazowa i
nadklasa
oraz
klasa pochodna i
podklasa i to tych zwrotów będziemy się trzymać.
Teraz, skoro poznaliśmy konwencję nazewniczą, możemy przystąpić do tematu przesłaniania metod.
Appa Notka. Zanim przystąpimy do omawiania metod, przypominamy, że modyfikator dostępu występujący zarówno w przypadku konstruktorów, metod, jak i klas jest opcjonalny. Nie musimy zawsze go wpisywać.
Jednak jeśli go ominiemy, wspomniane elementy będą miały ograniczoną widoczność w projekcie. W naszych przykładach dodajemy do metod i konstruktorów najczęściej modyfikator public, aby ułatwić Wam naukę podstaw języka, tak byście nie musieli
co chwilę zastanawiać się jaki rodzaj modyfikatora powinien zostać użyty w danym miejscu. Na takie zabawy przyjdzie jeszcze czas. Najpierw warto poznać zasady działania języka, a dopiero później wprowadzać do niego
ograniczenia, które wymagają wiedzy na odpowiednim poziomie - między innymi tej znajdującej się w rozdziale Modyfikatory dostępu i niedostępowe.
Sygnatura metody
Najpierw wyjaśnijmy jedno podstawowe pojęcie, takie jak sygnatura metody. Sygnaturą nazywamy
nazwę metody wraz z jej
parametrami.
W przypadku parametrów istotne jest, by miały taką samą liczebność, kolejność oraz takie same typy.
Nie ma natomiast znaczenia, jakie mają nazwy.
Do sygnatury metody
nie zalicza się
typ wartości zwracanej przez metodę. Zatem jeśli utworzymy metodę taką jak poniższa, wówczas będzie ona miała w dalszym ciągu tę samą sygnaturę,
co metoda wyżej.
Taka sama metoda w klasie bazowej i pochodnej
Teraz wyobraźmy sobie sytuację, w której zarówno w klasie bazowej, jak i klasie pochodnej mamy metodę o tej samej
sygnaturze.
Dodatkowo niech obie metody mają albo dokładnie ten sam typ zwracanej wartości, albo niech metoda klasy pochodnej zwraca typ rozszerzający typ zwracany przez metodę w klasie bazowej.
Ten sam
typ wartości zwracanej:
Typ rozszerzający (
String) typ wartości zwracanej (
Object):
Appa Notka. Jeśli nie wiesz, gdzie jest napisane to, że String rozszerza Object,
to wróć do rozdziału Klasy - Dziedziczenie
i przeczytaj raz jeszcze paragraf "Klasa Object". Dowiesz się z niego, skąd się bierze nasze stwierdzenie o dziedziczeniu z tej klasy.
W tym miejscu możemy powiedzieć, że właśnie zaimplementowaliśmy mechanizm nazywający się
przesłonięciem metody.
Metoda
getName znajdująca się w klasie pochodnej przesłania metodę
getName znajdującą się w klasie
bazowej. Teraz zobaczmy, jakie to ma konsekwencje w kontekście wykonywanego programu.
Uruchamiając taki kod,
najpierw wydrukujemy na konsoli tekst "Simple Item", a
następnie..."Document Item".
Dzieje się tak, mimo że wcześniej zarówno w obiekcie
item jaki i w obiekcie
item2 ustawiliśmy tę samą nazwę - "Simple Item". Powstaje więc pytanie, co się właściwie stało?
Odpowiedzią jest właśnie
termin
przesłonięcie metody. Zauważmy bowiem, że obiekt
item, to instancja klasy
Item,
podczas gdy obiekt
item2 to instancja klasy
DocumentItem. Skoro więc przesłoniliśmy metodę
getName
w klasie
DocumentItem, to w przypadku stworzenia obiektu tego typu, wykonana zostanie metoda przesłaniająca, a ona zwraca ustawiony na sztywno tekst "Document Item".
Appa Notka. Z tego co zauważyliśmy zdarzają się kursy, w których podczas przedstawiania tematu przesłaniania metody popełniany jest pewien błąd (wynikający pewnie z niedopatrzenia).
Czasem przesłanianie metody opisywane jest jako zgodność tylko i wyłącznie sygnatury metody. Jak wiemy typ zwracanej wartości nie wchodzi w skład sygnatury, a on jest tutaj również niezwykle istotny.
Zalecamy czujność w tym temacie. Pamiętajcie, że aby poprawnie przesłonić metodę musimy również zwracać uwagę na typ (musi być ten sam albo rozszerzający).
Super metoda w superklasie
Na początek mała uwaga. Co prawda mieliśmy zawsze używać słowa klasa bazowa albo nadklasa, ale jednak zrobimy jeden wyjątek. Jak wiemy, klasa bazowa nazywana jest czasem superklasą.
Nie ma w tym nic dziwnego, bo żeby powstała jakakolwiek klasa pochodna musi istnieć najpierw klasa wzorcowa - superklasa. Termin ten przyda się teraz, aby zrozumieć, do czego służy w Javie słowo kluczowe
o nazwie
super.
Jeśli w podklasie chcemy wywołać kod
przesłoniętej metody z superklasy, wówczas
używamy słowa kluczowego super:
Wywołanie programu klasy
Start (zdefiniowanej tak jak poprzednio) będzie szczególnie ciekawe w przypadku obiektu
item2.
Mamy tu do czynienia z instancją klasy
DocumentItem, a to jak wiemy oznacza, że wywołujemy kod metody przesłaniającej.
W obecnym przypadku pierwszą instrukcją tej metody jest
"nakaz" wywołania metody z klasy bazowej (z superklasy).
Z tego powodu proces wykonawczy programu przejdzie do metody
getName w klasie
Item i wydrukuje na konsoli tekst
"Super metoda w superklasie".
Wykona się tu cała metoda
getName, a więc jako wynik tej metody zwrócona zostanie nazwa ustawiona w polu
name.
Nie będzie to jednak miało wpływu na dalszą część programu, gdyż obecnie nie przechwytujemy tego, co zwraca ta metoda.
Zaraz po tym proces wróci do klasy
DocumentItem i zwróci jako wynik (wykonania metody przesłaniającej) tekst "Document Item", który następnie zostanie wydrukowany na konsoli.
Przykład w programie
Teraz zobaczmy jak kod naszego programu wygląda w IDE:
Autor: Jarek Klimas
Data: 03 stycznia 2024
Labele: Backend, Podstawowy, Java
Czy informacje, które otrzymałeś, były pomocne?
Jeśli tak, zapraszam Cię do podarowania mi kawy.
Masz pytanie dotyczące prezentowanego materiału?
Coś jest dla Ciebie niejasne i Twoje wątpliwości przeszkadzają Ci w pełnym zrozumieniu treści?
Napisz do nas maila, a my chętnie znajdziemy odpowiednie rozwiązanie.
Najciekawsze pytania wraz z odpowiedziami będziemy publikować pod rozdziałem.
Nie czekaj. Naucz się programować jeszcze lepiej.