В каких случаях следует использовать публичные поля вместо свойств?

Возможное дублирование:
члены общедоступных данных против геттеров и сеттеров

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


person luvieere    schedule 17.08.2010    source источник


Ответы (6)


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

struct Simple
{
    public int Position;
    public bool Exists;
    public double LastValue;
};

Но разные люди по-разному думают:

http://kristofverbiest.blogspot.com/2007/02/public-fields-and-properties-are-not.html

http://blogs.msdn.com/b/ericgu/archive/2007/02/01/properties-vs-public-fields-redux.aspx

http://www.markhneedham.com/blog/2009/02/04/c-public-fields-vs-automatic-properties/

person BitKFu    schedule 17.08.2010
comment
Еще одно исключение, которое я сделал бы в .net, было бы чем-то вроде класса MutableHolder<T>, единственная цель которого - предоставить доступ к общедоступному полю типа T. Обертывание Interlocked-совместимых элементов коллекции в таком классе при их хранении в коллекции позволит использовать для них Interlocked методы, даже если коллекция не поддерживает такие вещи, а обертывание типов значений в таких классах позволит их изменять. напрямую, не изменяя базовую коллекцию. Можно удерживать более одного элемента в объекте класса, используя PODS с открытым полем в качестве параметра типа. - person supercat; 29.11.2012

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

Кроме того, я не вижу необходимости в хороших принципах ООП.

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

person Oded    schedule 17.08.2010
comment
Я не уверен, всегда ли желательна общедоступная константа. С этого момента такое значение является частью API, и вы, возможно, не сможете легко удалить / изменить его. - person soulmerge; 17.08.2010

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

Но, честно говоря, я не знаю языка, на котором это правда. По крайней мере, как в .NET, так и в Java это хорошо оптимизировано.

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

Ура Матиас

person Matthias Meid    schedule 17.08.2010

Давайте сначала рассмотрим вопрос зачем нам нужны аксессоры (геттеры / сеттеры)? Вам нужно, чтобы они могли переопределять поведение при присвоении нового значения / чтении значения. Возможно, вы захотите добавить кеширование или вернуть вычисленное значение вместо свойства.

Теперь ваш вопрос может быть сформулирован как всегда ли я хочу такое поведение? Я могу вспомнить случаи, когда это вообще бесполезно: структуры (что было structs в C). Передача объекта параметра или класса, обертывающего несколько значений для вставки в Коллекция - это случаи, когда на самом деле аксессоры не нужны: объект это просто контейнер для переменных.

person soulmerge    schedule 17.08.2010

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

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

Принуждение использовать get и set для каждого поля находится в противоречии с YAGNI принцип.

Если вы хотите раскрыть значение поля из объекта, тогда раскрывайте его! Совершенно бессмысленно создавать объект с четырьмя независимыми полями и требовать, чтобы все они использовали доступ к get / set или свойствам .

*: Другие причины, такие как возможное изменение типа данных, бессмысленны. Фактически, где бы вы ни использовали a = o.get_value() вместо a = o.value, если вы измените тип, возвращаемый get_value(), вам придется менять его при каждом использовании, как если бы вы изменили тип value.

person Didier Trosset    schedule 17.08.2010
comment
Я не думаю, что YAGNI заходит так далеко, что, возможно, вызывающий код не будет работать, когда мы выпустим более позднюю версию этого компонента. Я был бы уверен, что им это понадобится, поэтому вам нужно подумать о том, может ли вам потребоваться заранее изменить поле на свойство, поскольку такое изменение нарушит код вызова. - person Jon Hanna; 17.08.2010
comment
Как вы и написали, вы совершенно уверены. ЯГНИ говорит, что до тех пор, пока он вам действительно не понадобится, вы его не пишете. - person Didier Trosset; 17.08.2010
comment
Я сказал, что почти уверен в ценности юмора. Я на 100% уверен, что если я обновлю компонент, и многие другие компоненты перестанут работать, я не буду счастлив. Я не знаю, понадобится ли мне данное изменение, но если это невозможно сделать без нарушения работающего кода, то на YAGNI есть ограничения. - person Jon Hanna; 17.08.2010

Основная причина заключается не в инкапсуляции ООП (хотя люди часто говорят, что это так), а во всем, что касается управления версиями.

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

Свойство с именем Foo не будет обрабатываться извне так же, как публичное поле с именем Foo. В некоторых языках это явно (язык напрямую не поддерживает свойства, поэтому у вас есть getFoo и setFoo), а в некоторых - неявно (C # и VB.NET напрямую поддерживают свойства, но они не совместимы с двоичным кодом. с полями и кодом, скомпилированным для использования, поле сломается, если оно будет изменено на свойство, и наоборот).

Если ваш Foo просто выполняет «слепую» установку и запись нижележащего поля, то в этом случае в настоящее время нет преимущества инкапсуляции по сравнению с открытием поля.

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

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

person Jon Hanna    schedule 17.08.2010
comment
По крайней мере, в .net, если рассматриваемый тип представляет собой структуру, состояние которой отображается через свойства / поля, которые могут быть публично прочитаны и могут быть установлены, возможно, через конструктор, чтобы принимать любые комбинации значений, которые действительны для их соответствующих типов, свойства почти не дают преимуществ инкапсуляции, но имеют существенные недостатки. - person supercat; 29.11.2012