Oto jeden z artykułów o języku Java, który powstał w wyniku "ćwiartowania" już napisanego materiału na mniejsze części. Napisałem o przesłanianiu, teraz będzie o przeciążaniu. A zatem, przeciążanie metody w języku Java - oto temat dzisiejszego artykułu!
WYJAŚNIJMY SOBIE TO PRZECIĄŻANIE METODY W JĘZYKU JAVA
Na starcie informacja: nie myl pojęcia "przeciążanie" z pojęciem "przesłanianie"! Oba dotyczą metod, natomiast znaczą zupełnie inną operację.
A CO KONKRETNIE?
Przesłanianie metody czy też nadpisywanie (ang. overriding) to zdefiniowanie nowego zestawu instrukcji dla klasy potomnej (ewentualnie dołożenie nowych instrukcji do już istniejącego - instrukcja "super" dla niekumatych 😄). Przeciążaniem (ang. overloading) z kolei określamy zdefiniowanie nowej metody o tej samej nazwie. Innymi słowy, polega na dodaniu kolejnej metody o tej samej nazwie umieszczonej w tej samej klasie lub w klasie potomnej, która MUSI różnić się parametrami i MOŻE reprezentować inny typ zwracanej wartości. W ten sposób występuje kilka różnych metod o tej samej nazwie mogących wykonywać inne instrukcje. Można tak, lecz trzeba stosować się do pewnych zasad.
Wyobraźmy sobie metodę zwracającą kwadrat podanej liczby całkowitej:
public int getSquareOf(int x) {
return x*x;
}
a po pewnym czasie stwierdzamy, że przydałoby się "wsparcie" tej metody dla liczb zmiennoprzecinkowych typu "float". I co teraz, zmodyfikować tamtą?
public float getSquareOf(float x) {
return x*x;
}
Też można, tylko jak korzysta z niej tysiąc innych klas i zdążyłeś(-aś) do nich włożyć dane typu "int", to lipa 👎. W takiej sytuacji już lepiej przeciążyć metodę robiąc o tak:
public int getSquareOf(int x) {
return x*x;
}
public float getSquareOf(float x) {
return x*x;
}
Kompilator nie będzie mieć do tego żadnych obiekcji. Wprowadzając parametr formalny, "zobaczy" jakiego to jest typu i "dobierze" taką metodę jaka będzie odpowiadać zestawowi parametrów w sygnaturze metody 👍:
getSquareOf(6); // kompilator "sięgnie" do metody oczekującej parametru typu "int"
getSquareOf(8.99f); // kompilator "sięgnie" do metody oczekującej parametru typu "float"
WYCZUWASZ JAKIEŚ "ALE"?
Oczywiście, że jest! Ujmując prostymi słowy, warunkiem do zaakceptowania takiego manewru jest sprawienie, żeby kompilator mógł rozróżnić "wersje" metod po parametrach formalnych. Spójrz teraz na takie przeciążanie metody w języku Java - metody typu "void":
public void doSomething() {
// instrukcje
}
public void doSomething() {
// instrukcje
}
Jakim cudem kompilator ma rozróżnić te metody? Nawet zmiana typu zwracanej wartości nie pomoże:
public void doSomething() {
// instrukcje
}
public int doSomething() {
// instrukcje
}
a to dlatego, że możesz bez problemu wywołać metodę zwracającą wartość bez podstawiania wyniku do zmiennej:
doSomething();
doSomething();
co innego jak dasz każdej metodzie inne parametry formalne jakich będzie oczekiwać:
public void printText(int n) {
System.out.println("Wypisuję liczbę całkowitą: " + n);
}
public void printText(float f) {
System.out.println("Wypisuję liczbę zmiennoprzecinkową: " + f);
}
public void printText(boolean b) {
System.out.println("Wypisuję wartość logiczną: " + b);
}
wtedy będąc zmuszonym do dostosowania się, nie dojdzie do jakiejkolwiek niejednoznaczności i operacja będzie "legitna":
printText(6);
printText(15.4f);
printText(true);
Wniosek z tego płynie taki, że:
- musisz zapewnić INNĄ listę parametrów formalnych,
- nie musisz deklarować innego typu danych jaka każda z przeciążonych metod ma zwracać (może być ich 100 i każda z nich być typu "void").
Przeciążanie metody w języku Java to zdefiniowanie co najmniej dwóch osobnych metod o tej samej nazwie, które muszą różnić się listą parametrów formalnych, lecz typy zwracanych wartości mogą zachować względem siebie takie same.
Tak się sprawy mają. Zapamiętaj sobie raz na zawsze: przeciążanie metody, a jej przesłanianie, to są dwie ZUPEŁNIE RÓŻNE czynności!