Открытый закрытый принцип

Я понимаю, что этот принцип гласит, что модуль открыт для расширения, но закрыт для модификации, и это ясно, когда мы хотим обновить / модифицировать метод в некотором классе - мы создаем другой класс, который наследует базовый класс, а затем переопределяем базовый метод. здесь, чтобы сохранить обе функциональные возможности.

Но как насчет случая, когда мы хотим добавить другой базовый метод в базовый класс? Считается ли это модификацией или расширением базового класса - можно ли добавить метод в базовый класс, или мы должны также создать новый класс, который наследует базовый класс, а затем поместить новый метод туда?

Кроме того, тот же вопрос для добавления свойств и полей в базовый класс.

1 ответ

Решение

TL;DR
Я думаю, что добавление нового метода по сути означает, что вы не можете нарушать OCP; поскольку OCP в основном фокусируется на безрассудном переопределении существующих методов.


Пример:
Базовый класс Calculator наследуется MyCustomCalculator, Базовый класс имеет только методы для сложения, вычитания, умножения и деления двух чисел.
Создание нового метода в MyCustomCalculatorнапример, CalculateAverage(params int[]) не нарушает OCP. Он не изменяет логику любого из существующих методов, он просто расширяет методы, предоставляемые объектом калькулятора.

Новые методы по своей сути не меняют старые методы. Следовательно, они не модифицируют существующую логику; тогда просто расширяйте то, что доступно.

Так что нет, это (по своей сути) не нарушает OCP.

Для него почти невозможно нарушить OCP, поскольку создание чего-то нового (по своей сути) полностью отличается от модификации чего-то, что существует.


Некоторые вещи, чтобы принять к сведению, хотя:

  • Я могу думать о (спорное) исключение: перегрузки. Если вы создаете новый метод, который перегружает существующий, вы обязаны соблюдать правила перегрузки. В частности, это означает, что перегруженные методы должны выполнять ту же задачу, что и остальные (перегруженные методы просто основаны на разных входных параметрах, но их обработка и вывод должны быть функционально эквивалентны). Хотя я не уверен на 100%, является ли это нарушением OCP (потому что он неправильно расширяет базовый класс), или SRP (потому что это создает неоднозначную ответственность за обработку / вывод перегруженных методов). Кажется, что-то и другое.
  • Тот же принцип применяется, даже если ваш новый метод не перегружает существующий. Достаточно ли уместен новый метод для ответственности (намерения / цели) базового класса? Потому что, если он сильно отличается, значит, вы нарушаете SRP.

РЕДАКТИРОВАТЬ

Я пропустил часть вашего вопроса

Это нормально, чтобы добавить метод в базовый класс, или мы должны также создать новый класс, который наследует базовый класс, а затем поместить новый метод там?

Это зависит от контекста. Для Calculator / MyCustomCalculator / CalculateAverage() пример, который я привел; Я бы инстинктивно добавил его в базовый класс, так как вычисление средних значений - это базовая операция, которая относится к обязанностям калькулятора.

Однако, если бы мы обсуждали добавление метода, который относится только к комплексным числам (MethodForComplexNumbers()), то я бы выступил за создание ComplexNumberCalculator который наследует от Calculator и реализует MethodForComplexNumbers(),

Тем не менее, я думаю, что это в основном из-за SRP, а не OCP.

Другие вопросы по тегам