Использование приватных (private) и защищенных (protected) полей

Рейтинг: 3Ответов: 2Опубликовано: 07.01.2015

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

class SimplePdoWrapper
{
    /** @type PDO */
    protected $pdo;
}

$pdo - это ресурс, через который посылаются запросы к базе данных. Я должен объявлять его как protected или как private? Как понять, нужно ли предоставлять прямой доступ к этому полю отнаследованному классу? Я отлично понимаю фразу "closed for modification, opened for extension", но как только подожу на практике, у меня начинается ступор: если я скрою эти поля, будет ли это означать ограничение расширяемости?

Ответы

▲ 5Принят

Упрощённо говоря, придерживайтесь следующего правила: объявляйте приватным всё, что можно.

Вы не должны оставлять поле или метод доступными наследнику «на всякий случай», вы должны понимать, почему без него наследникам не обойтись. Конечно, «open for extension» — это правильно, но в принципе расширение функциональности должно быть возможно не заглядывая в «грязное бельё» текущей имплементации.

Если вы строите иерархию классов, вам придётся для начала её спланировать. Вы должны прикинуть, какие непубличные свойства/методы являются важными для расширения (их должно быть по идее совсем немного), а какие не нужны, порождённый класс вполне может обойтись официальными, публичными методами. Прокрутите в голове несколько вариантов расширения.

Возможно, с первого раза получится неоптимально, и придётся пересматривать структуру. С практикой придёт опыт.

▲ 2

В многих случаях действительно очень сложно вначале решить, какие поля видимости дать для каждого метода (функции) и полей. Как распределять - приходит с опытом.

Когда мне нужно написать класс для какой-то работы, я тоже не всегда знаю, какую видимость дать для каждого поля. Поэтому делаю минимальную видимость. Если поле не будет использоваться вне - приватную, если будет - публичную. protected появляется тогда, когда появляется наследование.

Но некоторым полям обычно легко указать видимость. К примеру, если это ресурс (как в Вашем примере), то по умолчанию я бы делал его приватным. А также некоторые методы-обертки (для открытия и закрытия подключения, получения данных). А вот protected подобные поля делать не нужно. Максимум, что можно сделать, - это protected константный геттер.

Поэтому мой любимый совет - перестать ныть и писать код. По ходу написания кода будет понятно, как все сделать.