Это - плохая практика, чтобы заставить метод set возвратить “это”?

Следующее должно возвратить булевскую переменную:

callable(x)
233
задан Ken Liu 27 August 2009 в 17:33
поделиться

15 ответов

Я не думаю, что в этом есть что-то особенное, это просто вопрос стиля. Это полезно, когда:

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

Альтернативами этому методу могут быть:

  1. Один мега-конструктор (обратная сторона: вы можете передавать много нулей или значений по умолчанию, и становится трудно понять, какое значение чему соответствует)
  2. Несколько перегруженных конструкторов (обратная сторона: становится громоздкой, когда у вас их несколько)
  3. Заводские / статические методы (обратная сторона: такие же, как перегруженные конструкторы - становятся громоздкими, когда их больше, чем несколько)

Если вы собираюсь установить только несколько свойств за раз. Я бы сказал, что не стоит возвращать «это». Он определенно упадет, если вы позже решите вернуть что-нибудь еще, например, индикатор состояния / успеха / сообщение.

75
ответ дан 23 November 2019 в 03:32
поделиться

Из заявления

list.add(new Employee().setName("Jack Sparrow").setId(1).setFoo("bacon!"));

я вижу две вещи

1) Бессмысленное утверждение. 2) Недостаточная читаемость.

0
ответ дан 23 November 2019 в 03:32
поделиться

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

1
ответ дан 23 November 2019 в 03:32
поделиться

На первый взгляд: «Ужасно!»

Если подумать,

list.add(new Employee().setName("Jack Sparrow").setId(1).setFoo("bacon!"));

на самом деле менее подвержен ошибкам, чем

Employee anEmployee = new Employee();
anEmployee.setName("xxx");
...
list.add(anEmployee);

Так что довольно интересно. Добавление идеи в набор инструментов ...

1
ответ дан 23 November 2019 в 03:32
поделиться

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

Обычно это называется шаблоном построителя. или свободный интерфейс .

Он также распространен в Java API:

String s = new StringBuilder().append("testing ").append(1)
  .append(" 2 ").append(3).toString();
101
ответ дан 23 November 2019 в 03:32
поделиться

Если вы не хотите возвращать 'this' из установщика, но не Если вы не хотите использовать второй вариант, вы можете использовать следующий синтаксис для установки свойств:

list.add(new Employee()
{{
    setName("Jack Sparrow");
    setId(1);
    setFoo("bacon!");
}});

В стороне, я думаю, что он немного чище в C #:

list.Add(new Employee() {
    Name = "Jack Sparrow",
    Id = 1,
    Foo = "bacon!"
});
25
ответ дан 23 November 2019 в 03:32
поделиться

Раньше я предпочитал этот подход, но я отказался от него.

Причины:

  • Читаемость. Это делает код более читабельным, если каждый setFoo () находится в отдельной строке. Обычно вы читаете код намного больше раз, чем за один раз, когда вы его пишете.
  • Побочный эффект: setFoo () должен устанавливать только поле foo, ничего больше. Возвращается лишнее «ЧТО это было?»

В шаблоне Builder, который я видел, используется не соглашение setFoo (foo) .setBar (bar), а скорее foo (foo) .bar (bar). Возможно, именно по этим причинам.

Это, как всегда, дело вкуса. Мне просто нравится подход "минимум сюрпризов".

2
ответ дан 23 November 2019 в 03:32
поделиться

Я не знаю Java, но сделал это на C ++. Другие люди сказали, что из-за этого строки становятся очень длинными и их трудно читать, но я делал это много раз:

list.add(new Employee()
    .setName("Jack Sparrow")
    .setId(1)
    .setFoo("bacon!"));

Это даже лучше:

list.add(
    new Employee("Jack Sparrow")
    .Id(1)
    .foo("bacon!"));

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

8
ответ дан 23 November 2019 в 03:32
поделиться

Поскольку он не возвращает void, он больше не является допустимым установщиком свойств JavaBean. Это может иметь значение, если вы один из семи человек в мире, использующих визуальные инструменты Bean Builder, или один из 17 человек, использующих элементы JSP-bean-setProperty.

6
ответ дан 23 November 2019 в 03:32
поделиться

По крайней мере теоретически , это может повредить механизмы оптимизации JVM, установив ложные зависимости между вызовами.

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

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

5
ответ дан 23 November 2019 в 03:32
поделиться

Эта схема (каламбур) называется «свободный интерфейс» , становится довольно популярным сейчас. Это приемлемо, но не совсем моя чашка чая.

6
ответ дан 23 November 2019 в 03:32
поделиться

Подводя итог:

  • это называется «свободный интерфейс», или "цепочка методов".
  • это не "стандартная" Java, хотя в наши дни вы все чаще видите это (отлично работает в jQuery)
  • , он нарушает спецификацию JavaBean, поэтому он не работает с различными инструментами и библиотеками, особенно со сборщиками JSP и Spring.
  • это может помешать некоторым оптимизациям, которые JVM обычно делает
  • некоторые люди думают, что это очищает код, другие думают, что это "ужасно"

Пара других моментов, не упомянутых:

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

  • IDE не будут генерировать их для вас (по умолчанию).

  • Наконец, вот реальные данные. У меня были проблемы с использованием такой библиотеки. Конструктор запросов Hibernate является примером этого в существующей библиотеке. Поскольку методы Query set * возвращают запросы, Невозможно понять, просто взглянув на подпись, как ею пользоваться. Например:

     Query setWhatever (String what);
    
  • Это вносит двусмысленность: модифицирует ли метод текущий объект (ваш шаблон) или, возможно, Query действительно неизменяем (очень популярный и ценный шаблон), и метод возвращает новый. Это просто затрудняет использование библиотеки, и многие программисты не используют эту функцию. Если бы сеттеры были сеттерами, было бы понятнее, как им пользоваться.

83
ответ дан 23 November 2019 в 03:32
поделиться

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

3
ответ дан 23 November 2019 в 03:32
поделиться

Я за то, чтобы сеттеры возвращали this. Меня не волнует, не совместим ли он с фасолью. Для меня, если это нормально иметь выражение / оператор «=», то подходящие сеттеры, которые возвращают значения, - это нормально.

3
ответ дан 23 November 2019 в 03:32
поделиться

Это может быть менее читабельно

list.add(new Employee().setName("Jack Sparrow").setId(1).setFoo("bacon!")); 

или это

list.add(new Employee()
          .setName("Jack Sparrow")
          .setId(1)
          .setFoo("bacon!")); 

Это более читабельно, чем:

Employee employee = new Employee();
employee.setName("Jack Sparrow")
employee.setId(1)
employee.setFoo("bacon!")); 
list.add(employee); 
0
ответ дан 23 November 2019 в 03:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: