Прагматическое представление о частном по сравнению с общественностью

Я всегда задавался вопросом по теме public, protected и private свойства. Моя память может легко напомнить времена, когда я должен был взломать чей-то код и наличие взломанного - на переменные класса, объявленные как private всегда огорчал.

Кроме того, было (больше) времена, которые я записал классу сам и никогда не распознавал потенциального усиления приватизации свойства. Я должен отметить здесь, что использование общедоступного Вара не находится в моей привычке: Я придерживаюсь принципов ООП путем использования методов считывания и методов set.

Так, каково самое главное в этих ограничениях?

6
задан Aza 10 April 2013 в 04:55
поделиться

9 ответов

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

Внешнее (общественное) - это ваш контракт с остальным миром. Вы должны стараться, чтобы он был простым, понятным, очевидным, надежным и, что очень важно, стабильным.

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

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

Небольшой пример, предположим, что у нас есть:

class MyDate
{ 
    public int y, m, d;
    public void AdvanceDays(int n) { ... } // complicated month/year overflow
    // other utility methods
};

Вы не можете запретить пользователю класса игнорировать AdvanceDays () и просто сделать:

date.d = date.d + 1; // next day

Но если вы сделаете y, m, d закрытым и протестируйте все свои методы MyDate, вы можете гарантировать, что в системе будут только действительные даты.

7
ответ дан 8 December 2019 в 18:34
поделиться

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

Я согласен с тем, что частный может быть настоящей проблемой, особенно если вы расширяете классы из библиотеки. Некоторое время назад мне приходилось расширять различные классы из среды Piccolo.NET , и было приятно, что они объявили все, что мне было нужно, как protected вместо private , поэтому Я смог расширить все, что мне было нужно, без необходимости копировать их код и / или изменять библиотеку. Важный вывод из этого: если вы пишете код для библиотеки или другого «повторно используемого» компонента, вам действительно следует дважды подумать, прежде чем объявлять что-либо частным .

4
ответ дан 8 December 2019 в 18:34
поделиться

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

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

Другими словами, вы хотите скрыть некоторые внутренние компоненты вашего кода от интерфейса .

См. Несколько видеороликов об API, например этот доклад Google .

0
ответ дан 8 December 2019 в 18:34
поделиться

Лично я редко пользуюсь защищенными членами. Я обычно предпочитаю композицию , шаблон декоратора или шаблон стратегии . Очень мало случаев, когда я доверяю подклассу (программисту) правильно обрабатывать защищенные переменные. Иногда у меня есть защищенные методы, чтобы явно предложить интерфейс специально для подклассов, но на самом деле такие случаи редки.

В большинстве случаев у меня есть базовый класс absract только с общедоступными чистыми виртуальными машинами (сейчас речь идет о C ++), и реализующие классы реализуют их. Иногда они добавляют некоторые специальные методы инициализации или другие специфические функции, но все остальное является частным.

0
ответ дан 8 December 2019 в 18:34
поделиться

Прежде всего, «свойства» могут относиться к разным вещам на разных языках. Например, в Java вы имеете в виду переменные экземпляра, в то время как C # проводит различие между ними.

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

Причина, как уже упоминалось другими, - это инкапсуляция. И что нам дает инкапсуляция?

Гибкость

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

Например, мы можем решить внести такие изменения:

int getFoo()
{
  return foo;
}

int getFoo()
{
  return bar + baz;
}

Если бы мы не инкапсулировали 'foo' с самого начала, нам пришлось бы изменить гораздо больше кода. (кроме этой строки)

Еще одна причина инкапсулировать свойство - обеспечить способ пуленепробиваемости нашего кода:

void setFoo(int val)
{
  if(foo < 0)
    throw MyException(); // or silently ignore

  foo = val;
}

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

Если бы наша собственность была публичной, мы бы не смогли этого сделать!

0
ответ дан 8 December 2019 в 18:34
поделиться

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

0
ответ дан 8 December 2019 в 18:34
поделиться

Некоторые языки, например Smalltalk, вообще не имеют модификаторов видимости.

В случае Smalltalk все переменные экземпляра всегда являются закрытыми, а все методы всегда общедоступными. Разработчик указывает, что метод является «частным» - что-то, что может измениться, или вспомогательный метод, который сам по себе не имеет особого смысла - помещая метод в «частный» протокол.

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

(Примечание: «свойства» в Smalltalk - это просто методы получения и установки.)

0
ответ дан 8 December 2019 в 18:34
поделиться

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

2
ответ дан 8 December 2019 в 18:34
поделиться

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

Обратите внимание, что моим классам не нужно было обеспечивать безопасность; для этого в языке есть другие механизмы.

0
ответ дан 8 December 2019 в 18:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: