Ответ
Наследование следует применять, когда между классами существует строгое отношение "является" (is-a) и необходимо повторно использовать или расширить функциональность базового класса, сохраняя полиморфизм.
Критерии правильного использования:
- Соблюдение принципа подстановки Лисков (LSP): Объекты производного класса должны быть способны заменить объекты базового класса, не нарушая работу программы.
- Наличие общей абстракции: Классы-наследники представляют собой более специфичные типы родительского класса.
Правильный пример:
// Базовый класс: общая абстракция
abstract class Shape {
public abstract double calculateArea();
}
// Наследник: является (is-a) Shape и реализует специфичное поведение
class Circle extends Shape {
private double radius;
@Override
public double calculateArea() {
return Math.PI * radius * radius;
}
}
Когда НЕЛЬЗЯ использовать наследование:
- Чтобы просто переиспользовать код без логической связи (нарушает LSP).
- Для реализации отношения "имеет" (has-a). Вместо
class Car extends Engine(машина является двигателем?) используйте композицию:class Car { private Engine engine; }. - Если базовый класс не предназначен для расширения (например, не имеет
protectedметодов или документированного поведения для наследников).
Альтернатива: Часто композиция и интерфейсы (implements) предоставляют более гибкое и менее связанное решение.