Должны ли защищенные атрибуты всегда быть запрещены? - PullRequest
14 голосов
/ 16 сентября 2008

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

Используете ли вы защищенные атрибуты? для чего вы их используете?

Ответы [ 14 ]

0 голосов
/ 09 января 2010

Я использую защищенные переменные / атрибуты в базовых классах, которые, как я знаю, я не планирую менять на методы. Таким образом, у подклассов есть полный доступ к их унаследованным переменным, и у них нет (искусственно созданных) издержек прохождения через getters / setters для доступа к ним. Примером является класс, использующий основной поток ввода / вывода; нет особых причин не разрешать подклассам прямой доступ к базовому потоку.

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

Это проектное решение, основанное на том, насколько простой является переменная-член и как ожидается, что она будет такой в ​​будущих версиях.

Инкапсуляция великолепна, но она может зайти слишком далеко. Я видел классы, чьи собственные закрытые методы обращались к переменным-членам, используя только методы getter / setter. Это излишне, поскольку, если класс не может доверять своим собственным закрытым методам со своими собственными данными, кому он может доверять?

0 голосов
/ 09 января 2010

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

Если ваши пользователи связываются с вашим классом, это не ваша проблема. Каждый злонамеренный пользователь может добавить следующие строки при переопределении одной из ваших виртуалов:

(C #)

static Random rnd=new Random();
//...
if (rnd.Next()%1000==0) throw new Exception("My base class sucks! HAHAHAHA! xD");
//...

Вы не можете запечатать каждый класс, чтобы предотвратить это.

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

Но мне лично не нравится придерживаться принципа упа любой ценой. Особенно создание свойств с единственной целью сделать элементы данных приватными.

(C #):

private _foo;
public foo
{
   get {return _foo;}
   set {_foo=value;}
}

Это было мое личное мнение.

Но сделайте то, что требует ваш босс (если он хочет, чтобы частные поля, чем это сделать.)

0 голосов
/ 16 сентября 2008

В общем да. Защищенный метод обычно лучше.

При использовании существует уровень простоты, заданный с помощью защищенной переменной final для объекта, который является общим для всех дочерних элементов класса. Я бы всегда советовал не использовать его с примитивами или коллекциями, так как договоры невозможно определить для этих типов.

В последнее время я пришел отделить вещи, которые вы делаете с примитивами и необработанными коллекциями, от вещей, которые вы делаете с хорошо сформированными классами. Примитивы и коллекции ВСЕГДА должны быть частными.

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

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

0 голосов
/ 16 сентября 2008

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

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

Мой типичный пример - обработчик файлов / потоков. Вы хотите получить доступ к обработчику (то есть дескриптору файла), но хотите скрыть его от других классов. Это гораздо проще, чем написать для него функцию set / get.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...