Подтвердить что ты не робот

Когда имеет смысл использовать общественное поле?

Это вопрос, который у меня был на некоторое время:

Когда имеет смысл публиковать поле публично так?

public class SomeClass()
{
   public int backing;
}

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

Лучшей практикой в ​​Java и С# уже давно является использование getters/seters или свойств для доступа к полям.

public class SomeClass()
{
   private int backing;

   public int getBacking()
   {
      return backing;
   }

   public void setBacking(int v)
   {
      backing = v;
   }
}

С# превратил это в довольно простой синтаксис с автоматическими свойствами:

public class SomeClass()
{
   public int Backing { get; set; }
}

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

Почему бы просто не рассматривать публично объявленные поля как свойства (или методы) за кулисами? Таким образом, невозможно было бы разгневать развязывание богов и немного набрать текст для загрузки.

public class SomeClass()
{
   public int backing;   // The same as public int backing { get; set; }
}

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

EDIT: Спасибо за все ответы. Я чувствую, что, возможно, не все понимают мой вопрос. Когда общественное поле будет лучшим выбором, чем собственность? Почему это лучший выбор? Если единственная причина - удобство (меньше ввода и беспорядок), то что будет недостатком того, чтобы компилятор генерировал свойство "под капотом" всякий раз, когда встречается публичное поле. В принципе, было бы невозможно создать истинное публичное поле (потому что все они были бы свойствами). Что было бы неправильно с этим? Спасибо.

4b9b3361

Ответ 1

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

Имейте в виду принцип open/close.

Ответ 2

Когда есть смысл публиковать поле открыто?

Среди других мест, в частных классах, как показано ниже.

public class MyOuterClass
{
      private class MyInnerClass
      {
            public int val ; // why bother w/boiler plate
      }
}

Ответ 3

Вот резюме плюсов и минусов публичных полей:

<сильные > Преимущества

  • Меньше помех в коде
  • Лучшая производительность (в некоторых случаях)

Недостатки

  • Представление не может быть изменено без изменения API
  • Инварианты не могут применяться (если поле не является неизменным)
  • Никаких дополнительных действий при доступе к этим полям

Итак, когда мы должны использовать публичные поля? Зависит. Очевидно, что для общественных классов недостатки перевешивают преимущества. Возможные проблемы с изменением кода внутри пакета намного хуже, чем больше помех в коде и незначительное влияние на производительность.

Однако класс может быть закрытым или частным вложением, и в этом случае вероятные изменения кода будут локализованы. Поэтому абсолютно возможно использовать публичные поля. Также есть случаи, когда разница в производительности не так мала. Например, руководство Android Developers утверждает, что использовать прямой доступ к полям вместо getters/seters, где это возможно, потому что это в несколько раз быстрее.

Подводя итог, я приведу одну из моих любимых книг "Эффективная Ява" Дж. Блоха, пункт 14:

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

Ответ 4

Я думаю, что имеет смысл, если вы хотите сгруппировать некоторые переменные/объекты (вроде C struct). Например:

class Pixel {
  public int x;
  public int y;
  Color c;
  // Other Pixel related information
}

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

Ответ 5

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

Например, см.

public const double PI

определенный в System.Math.

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

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

Ответ 6

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

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

Ответ 7

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

/** 
 * A two-dimensional mathematical vector. Immutable so instances may be freely shared
 * without violating encapsulation.
 */
public class Vec2 {
    public final int x, y;

    // bunch of constructors and methods omitted
}

Обоснование. Очень маловероятно, что внутреннее представление необходимо будет изменить или выполнить какую-либо операцию при чтении x или y. То есть использование сеттера не приносит никакой пользы.

Однако это принесет некоторые издержки:

  • В публичном финальном поле будет совершенно ясно, что класс неизменен, с геттером, вы должны доверять комментарию документации. (Обратите внимание, что отсутствие сеттера не подразумевает неизменности, поскольку какой-либо другой метод может назначить поле)
  • Кодирование доступа к вектору будет несколько менее читаемым, так как get() не содержит смысловой семантической информации, но при чтении кода он все же должен быть пропущен (по крайней мере, на Java, С# здесь лучше).
  • Это очень частое использование класса крайне низкого уровня, и проблемы с накладными расходами могут стать проблемой. Да, виртуальная машина может выполнять inlining во многих случаях, но, по крайней мере, для не конечных методов, некоторые издержки, вероятно, останутся, даже если подклассы в настоящее время не загружены.

Ответ 8

Один сценарий, по крайней мере, в .NET, взаимодействует с C API. Вы часто объявляете С# или VB-версии структур Windows API, и для них обычно используются публичные поля, потому что нормальная причина для создания полей private - для предотвращения того, чтобы кто-то возился с ними за вашей спиной - ломался. В этом случае вы знаете, что что-то изменит поля за вашей спиной - что вся цель иметь структуру!

Конечно, вы обычно не будете раскрывать эти неинкапсулированные структуры в код приложения - вы будете рассматривать их как частные элементы модуля P/Invoke, поэтому код приложения все равно не будет иметь дело с публичными полями.

Ответ 9

Лучшей практикой в ​​Java и С# уже давно является использование getters/seters или свойств для доступа к полям.

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

Крайние случаи - вообще не иметь никаких мутаторов. Заключительным этапом создания неизменяемого класса никогда не будет являться изменчивое значение поля (помните, что Java final не похож на С++ const), напрямую доступный. И классы малых значений должны быть неизменными. Только метод getter может обеспечить безопасный доступ к потенциально изменяемым полям, создав копию (на С++ у вас есть только получатель, который возвращает значение). Вы можете обойтись без получателя для тех полей, которые не требуют защитного копирования, но тогда некоторые поля в классе могут потребовать получение, а некоторые нет. Но это будет путать,

Ответ 10

Вы можете использовать в java публичное поле, а затем добавить к нему какую-то логику, например, если бы был getter, используя AspectJ, в том числе избегать записи на него, если не из определенного psckage и т.д.

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

Вернемся к вашему вопросу, так как jit не улучшает использование публичных полей, а не геттеров/сеттеров, и поскольку у IDE есть автоматическое создание геттеров и сеттеров, нет реальных накладных программистов при использовании геттеров и сеттеров. В годы программирования Java я использовал публичные поля только пару раз и всегда заканчивал их преобразование в пары getters/seters.