2013-06-30 2 views
5

Мой вопрос относится к Java, но он также может применяться к C#. Мне было интересно, почему все рекомендуют делать переменные экземпляра частным в отличие от их создания защищено.Почему рекомендуется указывать переменные экземпляра как частные?

Давайте просто подумаем об этом. Частные переменные не рассматриваются подклассом, поэтому, если мне нужно получить доступ или изменить переменные суперкласса в моем подклассе, я вынужден использовать некоторый метод доступа и мутаторов, например getMyPrivateVariable или setMyPrivateVariable. Но когда вы расширяете некоторый класс и наследуете его члены, это работает так, как будто вы объявили их непосредственно в подклассе. Поэтому логически это означает, что подкласс должен также иметь прямой доступ к переменным экземпляра и делает случай для проектирования класса с защищенными переменными. Я понимаю, что такая практика нарушит инкапсуляцию, но это кажется неуместным в случае наследования, потому что, опять же, в этом случае все работает так, как если бы члены суперкласса были объявлены в подклассе, поэтому подкаска имеет «естественное право», за возможность напрямую обращаться к своим членам, независимо от того, были ли они унаследованы или нет. Инкапсуляция, на мой взгляд, важнее для взаимодействия с объектом другими объектами, которые находятся за пределами дерева наследования объекта.

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

+0

Это вопрос подходящий для программистов.stackexchange.com, а не для StackOverflow. – m3th0dman

+0

Не все _ делает. Но из вашего текста кажется, что вы поняли «защищенный»; в любом случае, делайте то, что считаете правильным. – fge

+5

Просто потому, что класс позволяет наследование не означает, что он хочет разрешить произвольное повреждение своих внутренних инвариантов дочерними классами. Создание полей (и некоторых методов) 'private' позволяет это. – dlev

ответ

1

Ответы на него сами - инкапсуляция.

Например, у вас есть абстрактный класс Cat. Это определяет переменную-переменную-члена, то есть как быстро она работает.

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

Теперь - если подклассы Cat - например, Moggy или Tabby могли получить доступ и модифицировать «скорость» напрямую, тогда это может сломать метод запуска.

Так что лучше всего держать его связанным там, где оно начинается. Вы также можете объявить его локально, если вам нужно.

0

, если мне нужно, чтобы получить доступ или изменить наследуемые переменные в моем подклассу я вынужден использовать некоторые аксессор [...]

Там вы его неправильно: private члены не наследуется , Вы можете ввести в заблуждение смысл «наследовать» тем, что экземпляр подкласса обладает всеми членами его суперклассов.

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

Пользователи объявлены protected только при проектировании класса specfically, который будет использоваться подклассов: в этом случае protected члены фактически являются частью его публичного API. Большинство классов не, предназначенные для общедоступного расширения, но объявление их final часто не является вариантом. Если бы у таких классов были все их члены protected, было бы равнозначно сделать их public, поскольку любой клиентский код мог бы тривиально сделать свой фиктивный подкласс, не добавляя ничего к родительскому, но подвергая его внутренности.

+0

Марко, это неправильно. Я знаю, что частные переменные недоступны подклассу, но защищены. В этом весь мой вопрос: зачем скрывать структуру данных суперкласса от подкласса. – akhilless

+0

Вы сказали, что хотите получить доступ к унаследованным переменным, которые недоступны; на что я отвечаю: «они не унаследованы». –

+0

Я спрашивал о правильности объявления переменных экземпляра private, а не защищенных. Часть, которую вы цитируете, гласит: «Частные переменные не рассматриваются подклассом», поэтому я знаю, что они не наследуются. Я исправил опечатку, и я удалил это слово «унаследовал» из этого места, чтобы сделать мою мысль более ясной. С другой стороны, разве вы не считаете, что создание фиктивного подкласса, предоставляющего доступ к унаследованным (защищенным) переменным суперкласса, фактически предоставляет внутренности подкласса, поскольку вы не можете вызывать эти методы на объекте суперкласса? – akhilless

0

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

Другими словами, у вас должна быть причина объявить член чем-то, кроме private. После того, как у вас есть веская причина, увеличьте видимость до минимально возможной степени (первым выбором должен быть пакет частный/по умолчанию видимость). Это потому, что вы должны находиться под полным контролем (или, по крайней мере, иметь некоторый контроль) кода в своем пакете, поэтому изменения там могут выполняться изолированно. В качестве побочного примечания «частный пакет» является единственным уровнем видимости (кроме public), который может быть применен к классам самого высокого уровня. Поэтому вам следует рассмотреть возможность удаления модификатора public из классов, которые не используются вне их пакета.

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

Что касается public, хорошей практикой было бы использовать его только для методов, объявленных в интерфейсах, которые вы реализуете.

0

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

0

ИМХО это философский вопрос. Но я думаю, что это вопрос о добавлении безопасного слоя в доступ к переменной экземпляра.

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

Таким образом, в основном это добавляет уровень безопасности и дает вам больше контроля над вашими переменными.

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

0

Суть объектно-ориентированного программирования является отправки сообщения, означая favorising поведение над данных.

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

Клиенты не должны брать некоторые данные со всего мира и самостоятельно выполнять логику (логика, которая не является частью их ответственности), они должны Tell! Don't Ask!. Они не должны осваивать необходимый алгоритм, который должен быть ролью целевого класса.

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

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

Кроме того, избегайте геттеров/сеттеров, когда вы не имеете дело с структурой данных. Действительно, это будет способствовать поведенческим методам.

Действительно, в 95% случаев геттер/сеттер очень плохие (не реализуйте ценную логику), и это просто конец, чтобы сделать вашу переменную public/protected.

Смежные вопросы