Способность Java делать выбор метода, исходя из типа времени выполнения, называется динамическим полиморфизмом. Поиск метода происходит сначала в данном классе, затем в суперклассе, пока метод не будет найден или не достигнут Object – суперкласс для всех классов.
Отметим, что статические методы могут быть переопределены в подклассе, но не могут быть полиморфными, так как их вызов не затрагивает объекты.
Если два метода с одинаковыми именами и возвращаемыми значениями находятся в одном классе, то списки их параметров должны отличаться. Такие методы являются перегружаемыми (overloading). Если метод подкласса совпадает с методом суперкласса (порождающего класса), то метод подкласса переопределяет (overriding) метод суперкласса. Все методы Java являются виртуальными (ключевое слово virtual, как в C++, не используется). Переопределение методов является основой концепции динамического связывания, реализующей полиморфизм. Когда переопределенный метод вызывается через ссылку суперкласса, Java определяет, какую версию метода вызвать, основываясь на типе объекта, на который имеется ссылка. Таким образом, тип объекта определяет версию метода на этапе выполнения. В следующем примере рассматривается реализация полиморфизма на основе динамического связывания. Так как суперкласс содержит методы, переопределенные подклассами, то объект суперкласса будет вызывать методы различных подклассов, в зависимости от того, на объект какого подкласса у него имеется ссылка.
/* пример # 4 : динамическое связывание методов :
DynDispatch.java */
class A {
int i, j;
public A(int a, int b) {
i = a;
j = b;
}
void show() { // вывод i и j
System.out.println("i и j: " + i + " " + j);
}
}
class extends A { B
; int k
public int a, int b, int c) { B(
super(a, b);
k = c;
}
void show() {
/* вывод k: переопределенный метод show() из A */
super.show(); // вывод значений из A
System.out.println("k: " + k);
}
}
class C extends B {
int m;
public int a, int b, int c, int d) { C(
super(a, b, c);
m = d;
}
void show() {
/* вывод m: переопределенный метод show() из B */
super.show(); //вывод значений из B
// show();
/*нельзя!!! метод будет вызывать сам себя, что приве-
дет к ошибке во время выполнения */
System.out.println("m: " + m);
}
}
public class DynDispatch {
public static void main(String[] args) {
A Aob;
B Bob = new B(1, 2, 3);
C Cob = new C(5, 6, 7, 8);
Aob = Bob; // установка ссылки на Bob
Aob.show(); // вызов show() из B
System.out.println();
Aob = Cob; // установка ссылки на Cob
Aob.show(); // вызов show() из C
}
}
Результат:
i и j: 1 2
k: 3
i и j : 5 6
k:7
m: 8
Следует помнить, что при вызове show() обращение super всегда происходит к ближайшему суперклассу.