Инициализация поля в конструкторах классов: прямая или через «сеттер» - PullRequest
1 голос
/ 09 февраля 2011

Я работаю над проектом Java по прошествии некоторого времени, используя C ++ и C #, и у меня есть сомнения относительно лучших практик для инициализации поля в конструкторах.Предположим, у меня есть простой класс Point.В C ++ моя инициализация поля в конструкторе будет выглядеть следующим образом:

class Point {
public:
    // Default constructor
    Point(double x, double y) : x(x), y(Y) { }

protected:
   // Coordinates
   double x, y;
};

В C # ...

class Point {
    // Coordinates, with automatic properties
    public double X { get; protected set; }
    public double Y { get; protected set; }

    // Default constructor
    Point(double x, double y) {
        X = x;
        Y = y;
    }    
}

В Java ... лучшие практики будут предлагать определять методы получения / установки дляполя, которые должны быть доступны снаружи.Но желательно ли использовать их и внутри класса?Сомнение возникает из-за того, что Eclipse, кажется, устраивает преобразование каждого this.field = field в коде класса в setField(field) для полей, которые имеют методы получения / установки, даже если чтение / запись происходит изнутри кода класса (поэтому я бы не сталнужно использовать интерфейс класса).

Это в основном добавляет вызов функции для каждого доступа.Теперь, кроме случая, когда установка поля включает в себя какую-то другую операцию (например, проверки, обработку и т. Д.), Имеет ли это какой-то смысл?Здравый смысл подсказывает, что использование методов получения / установки аналогично использованию свойств C #, но здесь я специально задаю вопрос об автоматических свойствах C # , которые включают только базовый доступ, без какой-либо обработки.Таким образом, вопрос: есть ли польза в вызове методов получения / установки без дополнительной обработки изнутри кода класса?

СпасибоTunnuz

Ответы [ 4 ]

4 голосов
/ 09 февраля 2011

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

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

Лучшие практики - это использовать

  • Конструктор / Инициализатор Блок для инициализации полей-членов до его значения.
  • изнутри полей доступа к классу напрямую
  • извне класс использует геттеры / сеттеры

См. Также

2 голосов
/ 09 февраля 2011

Я бы тоже предпочел прямой доступ. Однако для нетривиальных get / setters вы можете использовать их, если внутренним компонентам также требуется нетривиальная семантика.

Если вы заранее не знаете, что get / setters будут не тривальными, то вы также, вероятно, заранее не знаете, должны ли внутренние компоненты выполнять дополнительную работу, поэтому преждевременная инкапсуляция может показаться полезным.

Моя установка Eclipse (Helios) не выполняет это преобразование, поэтому я предполагаю, что вы можете отключить его.

1 голос
/ 09 февраля 2011

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

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

public class Foo {

   private String bar;

   public Foo(String aValue) {

      if(aValue==null || aValue.equals("")) {
          throw new IllegalArgumentException("Duh");
      }

      bar=aValue;

   }

   public void setBar(String aValue) {

      if(aValue==null || aValue.equals("")) {
          throw new IllegalArgumentException("Duh");
      }

      bar=aValue;

   }
}

Используя сеттер, вы повторно используете код и позволяете реализовать больше логики в одной точке:

public class Foo {

   private String bar;

   public Foo(String aValue) {

      setBar(aValue);

   }

   public void setBar(String aValue) {

      if(aValue==null || aValue.equals("")) {
          throw new IllegalArgumentException("Empty values not allowed");
      }

      if(aValue.length()>24) {
           throw new IllegalArgumentException("Too long");
      }
      bar=aValue;

   }

}
0 голосов
/ 09 февраля 2011

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

...