Что означает принцип «класс открыт для расширения, но закрыт для изменений» (Open/Closed Principle)?

«Что означает принцип «класс открыт для расширения, но закрыт для изменений» (Open/Closed Principle)?» — вопрос из категории ООП, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Это Принцип открытости/закрытости (Open/Closed Principle, OCP), один из пяти принципов SOLID. Он гласит: программные сущности (классы, модули, функции) должны быть открыты для расширения, но закрыты для модификации.

  • Закрыты для изменений: Поведение базового класса не должно меняться путем правки его исходного кода. Это предотвращает появление ошибок в уже работающем коде.
  • Открыты для расширения: Новую функциональность следует добавлять путем создания новых классов (например, через наследование, композицию или реализацию интерфейсов).

Пример нарушения OCP:

class AreaCalculator {
    public double calculateArea(Object shape) {
        if (shape instanceof Circle) { // При добавлении новой фигуры нужно менять этот класс
            return ((Circle) shape).radius * ((Circle) shape).radius * Math.PI;
        } else if (shape instanceof Square) {
            return ((Square) shape).side * ((Square) shape).side;
        }
        throw new IllegalArgumentException("Unknown shape");
    }
}

Пример c соблюдением OCP:

// Абстракция, закрытая для изменений
interface Shape {
    double area();
}

// Расширения, не требующие изменения интерфейса
class Circle implements Shape {
    private double radius;
    public Circle(double radius) { this.radius = radius; }
    @Override
    public double area() { return Math.PI * radius * radius; }
}

class Square implements Shape {
    private double side;
    public Square(double side) { this.side = side; }
    @Override
    public double area() { return side * side; }
}
// Можно добавить класс Triangle, не меняя код Shape, Circle или Square.

Преимущества: Повышение стабильности, упрощение тестирования и снижение риска регрессионных ошибок.