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

Возможный дубликат:
Члены Public Data против Геттеров, Сеттеров

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

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/

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

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

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

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

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

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

Ура Матиас

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

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

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

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

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

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

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

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

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

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

Если ваш Foo просто делает "слепой" набор и запись базового поля, то в настоящее время нет преимущества в инкапсуляции по сравнению с экспозицией поля.

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

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

Другие вопросы по тегам