Если в иерархии классов имя и сигнатура типа метода подкласса совпадает с атрибутами метода суперкласса, говорят, что метод подкласса переопределяет метод суперкласса.
Скачать исходники для статьи можно ниже
Когда переопределенный метод вызывается из своего подкласса, он всегда будет ссылаться на версию этого метода, определенную подклассом. Версия метода, определенная суперклассом, будет скрыта.
.
.
.
.
Рассмотрим следующий пример.
// Переопределение метода. class A { int i, j; A(int a, int b) { i = a; j = b; } // отображение i и j void show() { System.out.println("i и j: " + i + " " + j); } } class В extends A { int k; В(int a, int b, int c) { super(a, b); k = с ; } // отображение k - этот метод переопределяет метод show() класса А void show() { System.out.println("k: " + k); } } class Override { public static void main(String args[]) { В subob = new В(1, 2, 3); subob.show(); // этот оператор вызывает метод show() класса В } }
Эта программа создает следующий вывод:
к: 3
Когда программа вызывает метод show() по отношению к объекту типа В, она использует версию этого метода, определенную внутри класса В. То есть версия метода show(), определенная внутри класса В, переопределяет версию, объявленную внутри класса А.
Если нужно получить доступ к версии переопределенного метода, определенного в суперклассе, это можно сделать с помощью ключевого слова super.
Например, в следующей версии класса В версия метода show(), объявленная в суперклассе, вызывается внутри версии подкласса. Это позволяет отобразить все переменные экземпляров:
class В extends А { int к; В(int a, int b, int с) { super(а, Ь); к = с; } void show () { super.show(); // этот оператор вызывает метод show() класса А System.out.println("k: " + k); } }
Подстановка этой версии класса А в предыдущую программу приведет к следующему
выводу:
i и j : 12
к: 3
В этой версии метод super.show() вызывает версию метода show(), определенную в суперклассе.
Переопределение метода выполняется только в том случае, если имена и сигнатуры типов двух методов идентичны. В противном случае два метода являются просто перегруженными.
Например, рассмотрим измененную версию предыдущего примера.
// Методы с различающимися сигнатурами являются // перегруженными, а не переопределенными, class A { int i, j ; A(int a, int b) { i = a; j = b; } // отображение i и j void show() { System.out.println("i и j: " + i + " " + j) ; } } // Создание подкласса за счет расширения класса А. class В extends A { int k; В(int a, int b, int с) { super(а, b); k = с; } // перегрузка метода show() void show(String msg) { System.out.println(msg + k); } } class Override { public static void main(String args[]) { В subob = new В (1, 2 , 3) ; subob.show("Это k: "); // вызов метода show() класса В subob.show(); // вызов метода show() класса A } }
Эта программа создает следующий вывод:
Это k: 3
i и j: 1 2
Версия метода show(), определенная в классе В, принимает строковый параметр.
В результате ее сигнатура типа отличается от сигнатуры метода в классе В,который не принимает никаких параметров. Поэтому никакое переопределение (или сокрытие имени) не происходит. Вместо этого просто выполняется перегрузка версии метода show (), определенной в классе А, версией, определенной в классе В.