SowingSadness
@SowingSadness
web-разработчик

Private методы и свойства

В каких случаях нужно предпочитать использовать private вместо protedted для методов и свойств класс?
Private полностью лишает нас возможности расширять класс — что на мой взгляд не логично.
У кого какие мысли или может уже кто-то знает ответ?
  • Вопрос задан
  • 13014 просмотров
Решения вопроса 2
@skvot
Область видимости метода всегда должна быть минимальна. Доступ к методу открывается только тогда, когда это действительно необходимо.
Ответ написан
OpenMinded
@OpenMinded
Если кратко, то лучше вообще забыть быть втройне осторожным с protected и особенно protected virtual, когда вы что-то проектируете. Проблемы будут как раз из-за того, что это не входит в интерфейс и почти всегда нарушает два принципа из SOLID, а именно Open/closed principle и Liskov substitution principle.

Нужно отличать расширение от модификации. Например, в родительском классе у вас есть метод, который пишет сообщение в поток. Если дочерний класс сначала вызовет метод родительского класса, а потом еще добавит сообщение в лог — это определенно расширение. Если дочерний класс добавит валидацию сообщения, которое пишется в поток, то это тоже расширение. Если же дочерний класс изменит само сообщение перед записью в поток, то это уже модификация.

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

Если этот метод был protected, то ни о каком интерфейсе тут речи уже нет. Разработчик должен гарантировать, что для клиента родительский класс и дочерний класс с перегруженным protected методом будут работать не просто одинаково хорошо, а вообще одинаково, так как клиент может получать экземпляр через конструктор и по интерфейсу и вообще быть не в курсе его реального типа.
Ответ написан
Пригласить эксперта
Ответы на вопрос 7
knekrasov
@knekrasov
Во-первых, открывать поля класса для публичного доступа — это почти всегда плохая идея.
Во-вторых, очень важно, чтобы API был лаконичным и кратким. Стороннему разработчику, который будет пользоваться вашим классом, не нужно видеть больше методов, чем может понадобиться по смыслу задачи (не перегружайте людей информацией и не раскрывайте деталей своей реализации).
Поэтому методы стоит определять как private по умолчанию. Если выяснится, что метод может потребоваться (или его поведение может уточниться) в потомке, то делайте его protected.

Делать публичными стоит только те методы, которые соответствуют смысловой абстракции.
Ответ написан
AR1ES
@AR1ES
Как сказали выше, private нужно использовать для тех переменных, которые не нужны будут наследникам класса для использования в явном виде.
Я, например, все переменные делают private и только при острой необходимости перевожу их в protected. Но чаще я делаю просто protected геттеры и сеттеры для этой переменной, т.к. как может возникнуть необходимость контролировать доступ к ней и из дочерних классов.
К тому же не забывайте, что в разных языках protected ведет себя по-разному. К примеру, в C++ protected позволяет дочерним классам иметь доступ к переменной, а в Java — дочерним классам, а так же всем остальным классам, находящимся в этом же пакете.
Ответ написан
@defuz
Private оправдан в тех случаях, если неправильное переопределение метода или атрибута наследником может привести к появлению некорректного состояния объекта (реализации нарушения инкапсуляции).

Ваша ошибка в том, что вы сравниваете protected в первую очередь c private, хотя на самом деле разница между protected и public намного меньше, чем между private и protected.

Рассматривайте public и protected как аpi вашего класса. Тольк public — это внешний api (для пользователей класса), а protected — внутренний (для наследников класса).
Ответ написан
Gero
@Gero
Пример: класс из сторонней библиотеки, который наследуется в вашей программе. В течение жизненного цикла вашей программы вы можете обновлять библиотеку на более новую версию, при этом ее внутренне устройство может меняться (private-методы), а интерфейсы, выставленные наружу — нет (в т.ч. и protected-интерфейсы). А вот если какие-то методы были объявлены как protected, то значительно изменять их поведение или декларацию — уже нельзя.
Ответ написан
Комментировать
kocherman
@kocherman
Не можете придумать пример? Вот только сейчас программирую класс клиента к серверам http и https. Предположим, есть класс Client, обобщающий HttpClient и HttpsClient. На тот класс ложится транспортная работа между приложением и протоколом. Внутри описания процессов работы класса Client часто используются функции, которые относятся непосредственно к уровню абстракции данного класса (соответственно, имеют доступ private). Например, сериализация массива заголовков запроса и его последующая отправка. То есть данная функция участвует в алгоритме Client, при этом такую функцию использовать где-либо еще бессмысленно, в том числе и в дочерних классах HttpClient и HttpsClient.
Ответ написан
Комментировать
@gro
Я могу сказать, что инкапсуляция скрывает реализацию и минимизирует интерфейс для клиента. Потомок в данном случае не является клиентом.

Потомок в данном случае является клиентом.
Есть класс и есть два способа его использовать — 1. работать с его экземпляром. 2. расширить его.
В классе прописывается, как интерфейс его непосредственного использования (public), так и интерфейс его расширения (protected).
Ответ написан
colonel
@colonel
Разработчик PHP, Laravel
На ваш вопрос нет однозначного ответа. Нет здесь волшебной пилюли )
Вы сами должны отвечать на него в каждом конкретном случае.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы