Переопределение
Переопределение методов:
- Создание в подклассе методов с тем же именем и набором параметров, как в суперклассе
- Меняется поведение наследника - не должен нарушаться контракт базового класса
- Метод наследника имеет то же имя и тот же набор параметров
- Меняется поведение наследника
Не путать с перегрузкой
Модификатор доступа при переопределении
Модификатор доступа можно только расширять, сужать - нет
Например, default -> public или private -> public
class Base {
protected int getVal() {
return 1;
}
protected static int statVal() {
return 3;
}
}
class Ext extends Base {
private int getVal() {
return 2;
}
private static int statVal() {
return 4;
}
}
getVal() in Ext cannot override getVal() in Base
attempting to assign weaker access privileges; was protected
Тип возвращаемого значения при переопределении
Тип возвращаемого значения тоже можно менять, он должен быть ковариантен исходному (то есть быть таким же, либо потомком)
class B {}
class D extends B {}
class A {
B method() {}
}
class C extends A {
@Override
D method() {} // OK
@Override
void method() {} // ERROR
}
Сигнатура метода при переопределении
Сигнатура должна совпадать, при этом имена параметров, как и положено, могут быть изменены
Аннотация @Override
При переопределении можно использовать аннотацию @Override - компилятор проверит, правильно ли вы переопределяете метод (сигнатуру, модификаторы)
Тип ошибки при переопределении
Если родительский метод выбрасывал ошибку через throws, то в переопределяемом методе можно сужать тип ошибки (указывать наследников)
class A {
protected void method() throws Exception {}
}
class B extends A {
@Override
public void method() throws IOException {}
}