SCJP - Przeciążanie metod
Kolejny zastrzyk wiedzy przed egzaminem SCJP – kontynuacja dzieła zapowiedzianego w artykule "Przygotowania do SCJP czas zacząć". Dziś będzie o przeciążaniu metod (ang. overloading).
Przeciążanie metod to definiowanie wielu metod o tej samej nazwie a różniących się listą argumentów. W zasadzie o metodzie przeciążającej – tj. używającej tej samej nazwy, co już istniejąca metoda – można myśleć jak o metodzie zupełnie nowej. Nie ma więc żadnych zasad ograniczających zwracany typ, deklarowane wyjątki czy modyfikatory dostępu, jako to ma miejsce w przypadku redefiniowania (ang. overriding). W zasadzie można by to sformułować następująco: jeśli chcemy zdefiniować metodę która będzie się nazywała tak samo jak inna, już istniejąca metoda to musimy określić inną listę argumentów. To tyle.
Mamy więc w naszej klasie zdefiniowanych kilka metod o tej samej nazwie, skąd więc wiadomo, którą z nich wywołujemy w danej chwili? Naturalnie, na podstawie listy parametrów, tyle, że nie zawsze sprawa jest bardzo prosta. Weźmy dla przykładu następujący program.
Przeciążanie metod to definiowanie wielu metod o tej samej nazwie a różniących się listą argumentów. W zasadzie o metodzie przeciążającej – tj. używającej tej samej nazwy, co już istniejąca metoda – można myśleć jak o metodzie zupełnie nowej. Nie ma więc żadnych zasad ograniczających zwracany typ, deklarowane wyjątki czy modyfikatory dostępu, jako to ma miejsce w przypadku redefiniowania (ang. overriding). W zasadzie można by to sformułować następująco: jeśli chcemy zdefiniować metodę która będzie się nazywała tak samo jak inna, już istniejąca metoda to musimy określić inną listę argumentów. To tyle.
Mamy więc w naszej klasie zdefiniowanych kilka metod o tej samej nazwie, skąd więc wiadomo, którą z nich wywołujemy w danej chwili? Naturalnie, na podstawie listy parametrów, tyle, że nie zawsze sprawa jest bardzo prosta. Weźmy dla przykładu następujący program.
class Test {
public static void main(String[] args) {
Test obj = new Test();
System.out.println(obj.getString(1));
}
String getString(float f) {
return "float value: " + f;
}
String getString(long l) {
return "long value: " + l;
}
}
Jaki jest efekt jego działania? Która z metod getString() zostanie wywołana? W tym wypadku efektem działania programu będzie napis "long value: 1". Autorzy książki nie podali w rozdziale drugim precyzyjnych reguł, ale intuicyjnie, wywoływana jest ta metoda, której argumenty "bardziej odpowiadają" przekazywanym parametrom. Szczegóły mają się pojawić w dalszych rozdziałach i póki co nie będę wybiegał przed szereg – poczekam. Popatrzmy jednak na jeszcze jeden przykład.
class Parent { }
class Child extends Parent { }
class Test {
public static void main(String[] args) {
Parent obj = new Child();
test(obj);
}
static void test(Parent p) {
System.out.println("method for Parent");
}
static void test(Child c) {
System.out.println("method for Child");
}
}
Efektem działania będzie napis "method for Parent", mimo, że obiekt, dla którego wywołano metodę test() jest klasy Child. Powód jest prosty – to, która z przeciążonych metod zostanie wywołana jest określane w czasie kompilacji, kiedy to nie wiadomo jeszcze, jaki będzie rzeczywisty obiekt, a więc o wywoływanej metodzie decyduje typ referencji nie zaś typ obiektu.
1 komentarz:
Wiadomo o co chodzi w pierwszym przykładzie. Kompilator jak i JVM najpierw stara się sprowadzić liczbę 1 do inta. Następnie szuka pierwszej pasującej metody. Nie ma dla int więc w kolejnym kroku szukamy najlepiej pasującej (long), a potem (ustalone eksperymentalnie) jest float, double. Short jako mniej dokładny wymaga rzutowania podobnie char.
Prześlij komentarz