В каких случаях в ООП следует применять наследование?

«В каких случаях в ООП следует применять наследование?» — вопрос из категории ООП, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Наследование следует применять, когда между классами существует строгое отношение "является" (is-a) и необходимо повторно использовать или расширить функциональность базового класса, сохраняя полиморфизм.

Критерии правильного использования:

  1. Соблюдение принципа подстановки Лисков (LSP): Объекты производного класса должны быть способны заменить объекты базового класса, не нарушая работу программы.
  2. Наличие общей абстракции: Классы-наследники представляют собой более специфичные типы родительского класса.

Правильный пример:

// Базовый класс: общая абстракция
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) предоставляют более гибкое и менее связанное решение.