Ответ
С корректным использованием наследования напрямую связан принцип Liskov Substitution Principle (LSP) — "Принцип подстановки Барбары Лисков".
Формулировка: Объекты базового класса должны быть заменяемыми объектами его подклассов без изменения корректности программы. Наследующий класс должен дополнять, а не изменять поведение родителя.
Суть принципа: LSP устанавливает строгие правила для наследования. Если класс S является подтипом класса T, то везде, где используется T, можно безопасно использовать S, не ломая логику.
Пример нарушения LSP:
class Rectangle {
protected int width, height;
public void setWidth(int w) { width = w; }
public void setHeight(int h) { height = h; }
public int getArea() { return width * height; }
}
// Квадрат «является» прямоугольником с математической точки зрения,
// но с точки зрения поведения — нет.
class Square extends Rectangle {
@Override
public void setWidth(int w) {
super.setWidth(w);
super.setHeight(w); // Нарушение: изменение высоты при установке ширины
}
@Override
public void setHeight(int h) {
super.setHeight(h);
super.setWidth(h); // Нарушение: изменение ширины при установке высоты
}
}
// Код, который работает с Rectangle, сломается для Square
void testArea(Rectangle r) {
r.setWidth(5);
r.setHeight(4);
assert r.getArea() == 20; // Утверждение провалится для Square (area=16)
}
Вывод: LSP требует, чтобы подклассы были семантически совместимы со своими суперклассами, а не только синтаксически. Наследование должно означать "является" в строгом поведенческом смысле.