Да, есть абсолютно причина, и эта причина - принцип замещения Лискова или «L» в «SOLID», если вы предпочитаете.
Принцип замещения Лиск утверждает, что если у вас есть тип T
и тип S
, который является подтипом T
, то вы должны быть в состоянии заменить любой объект типа T
с объектом типа S
без изменения правильности вашего программа.
protected
Члены являются распространенным методом создания нарушений подстановки Liskov, поскольку они позволяют вам перезаписывать поведение, обнаруженное в супертипе.
Это здорово в теории, но что это на самом деле означает?
is взаимосвязь, созданная наследованием, является чрезвычайно прочной связью между типами, гораздо более сильной, чем общий интерфейс или композиция, поскольку она подразумевает совместное использование. Классическим примером нарушения замещения Лискова является проблема Circle-Ellipse, см.: https://en.wikipedia.org/wiki/Circle-ellipse_problem
Эта проблема еще более значительна в мире производства, где другие разработчики могут в конечном итоге полагаться на поведение, которое, по их мнению, гарантировано наличие супертипа, но на самом деле не гарантируется вообще из-за нарушений LSP - в худшем возможном случае они могут в конечном итоге полагаться на неправильное поведение, так что законное исправление ошибок в суперклассе создает проблемы в другом месте.
Всякий раз, когда вы делаете объект/метод более доступным, чем private
, вы эффективно предоставляете гарантии другим разработчикам, которые в своем подтипе могут изменить любое конкретное поведение практически любым образом, и ваш код будет по-прежнему функционировать правильно, поэтому каждый вы принимаете это решение, вы должны спросить себя, насколько вы способны сделать эту гарантию. Если вы не уверены в этом, тогда не делайте этого.
Важно знать, что вы не пропустите детали реализации своего класса за пределами своих границ через членов protected
, как и через public
, потому что подводные камни могут быть немного неприятными.
Это одна из причин того, что композиция объекта обычно предпочтительна по сравнению с наследованием. Дело не в том, что с наследованием в принципе что-то не так, но связь между типом и супер-типом чрезвычайно сильная, и важно убедиться, что эти отношения используются только тогда, когда это уместно.
Давайте посмотрим на вашем примере, имеет код в private
статус, например. На данный момент этот код состояния является фактически неизменным, он устанавливается один раз в конструкторе и не может быть изменен каким-либо открытым способом в классе. Это хорошо, потому что это исключение, мы не хотим, чтобы он менялся, мы хотим знать о том, что изначально вызвало его.
Если бы вы были, чтобы сделать этих членов protected
, у вас нет никакой гарантии на это. Подтип HttpException
, который представляет собой одну ошибку за один момент, теоретически может представлять совершенно другую ошибку на следующем. В этой ситуации класс больше не имеет смысла, он не служит своей цели.
«Многие хорошие вопросы порождают определенное мнение, основанное на опыте экспертов, но ответы на этот вопрос будут иметь тенденцию почти полностью основываться на мнениях, а не на фактах, ссылках или конкретном опыте». –
В большом количестве кода, который я видел, 'private' был недостаточно использован, и объекты обрабатывались как записи с помощью методов. – reaanb
@reaanb Возможно, вы говорите о злоупотреблении 'public', но это обсуждение о' private' против 'protected', а не' private' vs. 'public'. –