Это хорошая или плохая идея, чтобы сеттеры в java возвращали "this"?
public Employee setName(String name){
this.name = name;
return this;
}
Этот шаблон может быть полезен, потому что тогда вы можете связывать сеттеры следующим образом:
list.add(new Employee().setName("Jack Sparrow").setId(1).setFoo("bacon!"));
вместо этого:
Employee e = new Employee();
e.setName("Jack Sparrow");
...and so on...
list.add(e);
... но это как бы идет вразрез со стандартным соглашением. Я полагаю, что это может стоить того, потому что это может заставить этого сеттера сделать что-то еще полезное. Я видел, как в этом шаблоне использовались некоторые места (например, JMock, JPA), но он кажется необычным, и обычно используется только для очень четко определенных API, где этот шаблон используется везде.
Обновить:
То, что я описал, очевидно справедливо, но я действительно ищу некоторые мысли о том, является ли это в целом приемлемым, и есть ли какие-либо подводные камни или связанные с ними лучшие практики. Я знаю о шаблоне Builder, но он немного сложнее, чем то, что я описываю - как описывает его Джош Блох, существует связанный статический класс Builder для создания объектов.
источник
this
. Иногда я даже изменяю функцию так, чтобы вместо возврата значения она работала с членом объекта, просто чтобы я мог это сделать. Это замечательно. :)Ответы:
Я не думаю, что с этим что-то конкретно не так, это просто вопрос стиля. Это полезно, когда:
Альтернативы этому методу могут быть:
Если вы собираетесь установить только несколько свойств одновременно, я бы сказал, что возвращать «this» не стоит. Конечно, он падает, если позже вы решите вернуть что-то еще, например, индикатор состояния / успеха / сообщение.
источник
Это не плохая практика. Это все более распространенная практика. Большинство языков не требуют от вас иметь дело с возвращенным объектом, если вы не хотите, чтобы он не изменял синтаксис «нормального» использования сеттера, но позволял вам связывать сеттеры вместе.
Это обычно называется шаблоном компоновщика или свободным интерфейсом .
Это также распространено в Java API:
источник
bla.foo.setBar1(...) ; bla.foo.setBar2(...)
когда вы можете писатьbla.foo /* newline indented */.setBar1(...) /* underneath previous setter */ .setBar2(...)
(не можете использовать разрывы строк в SO-комментарии, подобном этому :-( ... надеюсь, вы получите точку зрения, учитывая 10 таких установщиков или более сложные вызовы)Подвести итоги:
Пара других моментов, не упомянутых:
Это нарушает принцип, что каждая функция должна делать одну (и только одну) вещь. Вы можете или не можете в это поверить, но я думаю, что в Java это работает хорошо.
IDE не собираются создавать их для вас (по умолчанию).
И наконец, вот реальная точка данных. У меня были проблемы с использованием библиотеки, созданной следующим образом. Конструктор запросов Hibernate является примером этого в существующей библиотеке. Так как методы set * в Query возвращают запросы, невозможно определить, просто используя сигнатуру, как ее использовать. Например:
Он вводит неоднозначность: изменяет ли метод текущий объект (ваш шаблон) или, возможно, Query действительно неизменен (очень популярный и ценный шаблон), а метод возвращает новый. Это просто затрудняет использование библиотеки, и многие программисты не используют эту функцию. Если бы сеттеры были сеттерами, было бы понятнее, как их использовать.
источник
this
вряд ли сложная ракетостроение. :-)Я предпочитаю использовать методы with для этого:
Таким образом:
Предупреждение : этот
withX
синтаксис обычно используется для предоставления «установщиков» для неизменяемых объектов, поэтому вызывающие эти методы могут разумно ожидать, что они создадут новые объекты, а не изменят существующий экземпляр. Может быть, более разумная формулировка будет что-то вроде:С соглашением об именовании chainsetXyz () практически все должны быть счастливы.
источник
get
, aset
и awith
для каждого поля класса. Это все еще интересное решение, хотя. :)Project Lombok
«s@Getter/@Setter
аннотаций ... что бы фантастическим для построения цепочки. Или вы можете использовать что-то похожее наKestrel
комбинатор ( github.com/raganwald/Katy ), который используют изверги JQuery и Javascript.with
префикс другой конвенции. как @qualidafial привел пример. методы с префиксомwith
должны возвращать неthis
новый экземпляр, например текущий, ноwith
это изменение. Это делается, когда вы хотите, чтобы ваши объекты были неизменными. Поэтому, когда я вижу метод с префиксом,with
я предполагаю, что получу новый объект, а не тот же объект.Если вы не хотите возвращаться
'this'
из установщика, но не хотите использовать второй вариант, вы можете использовать следующий синтаксис для установки свойств:Кроме того, я думаю, что это немного чище в C #:
источник
equals
метод. Существуют очень простые способы работы с анонимными классами,equals
если вы знаете, что делаете.Он не только нарушает соглашение о методах получения / установки, но также нарушает структуру ссылок на методы Java 8.
MyClass::setMyValue
этоBiConsumer<MyClass,MyValue>
иmyInstance::setMyValue
естьConsumer<MyValue>
. Если у вас есть возвращаемый метод setterthis
, то он больше не является действительным экземпляромConsumer<MyValue>
, а скорее aFunction<MyValue,MyClass>
, и приведет к тому, что что-либо, использующее ссылки на методы для этих сеттеров (при условии, что они являются пустыми методами), будет повреждено.источник
Consumer<A>
иFunction<A,B>
предоставляя реализацию по умолчаниюvoid accept(A a) { apply(a); }
. Тогда он может легко использоваться как один из них и не будет нарушать любой код, который требует определенной формы.Я не знаю Java, но я сделал это на C ++. Другие люди говорили, что это делает строки очень длинными и очень сложными для чтения, но я делал это много раз:
Это даже лучше:
по крайней мере, я думаю. Но вы можете понизить меня и назвать меня ужасным программистом, если хотите. И я не знаю, разрешено ли вам даже делать это на Java.
источник
//
после каждого метода, если вы настраиваете свою IDE, не присоединять уже обернутые строки (например, Eclipse> Свойства> Java> Стиль кода> Форматер> Обтекание строк> Никогда не объединять обернутые строки).Эта схема (предназначенная для игр с каламбурами), называемая «плавным интерфейсом», сейчас становится довольно популярной. Это приемлемо, но это не совсем моя чашка чая.
источник
Поскольку он не возвращает void, он больше не является корректным установщиком свойств JavaBean. Это может иметь значение, если вы один из семи человек в мире, использующих визуальные инструменты Bean Builder, или один из 17, использующих элементы JSP-bean-setProperty.
источник
По крайней мере, теоретически , это может повредить механизмы оптимизации JVM, устанавливая ложные зависимости между вызовами.
Предполагается, что это синтаксический сахар, но на самом деле он может создавать побочные эффекты в суперинтеллектуальной виртуальной машине Java 43.
Вот почему я голосую "нет", не используйте его.
источник
set
метода зависит от первогоset
метода, хотя он известен программисту.-XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining
Java7 jdk однозначно встраивает цепочечные методы и делает примерно такое же количество итераций, которое требуется, чтобы пометить пустые сеттеры как горячие и встроить их тоже. Считаете, что вы недооцениваете силу алгоритмов сокращения кода операции JVM; если он знает, что вы возвращаете это, он пропустит код операции jrs (оператор возврата java) и просто оставит его в стеке.Это совсем не плохая практика. Но это не совместимо с JavaBeans Spec .
И много спецификаций зависит от этих стандартных средств доступа.
Вы всегда можете заставить их сосуществовать друг с другом.
Теперь мы можем использовать их вместе.
Вот еще одна версия для неизменного объекта.
Теперь мы можем сделать это.
источник
some
поле. Во- вторых, вы должны добавить гарантию и наборsome
дляnull
телосложением () , так чтоSome
это действительно неизменны, в противном случае вы могли бы назватьbuilder.value()
на том же экземпляре Builder снова. И, наконец, да, у вас есть конструктор, но у васSome
все еще есть публичный конструктор, что означает, что вы не пропагандируете использование конструктора открыто, т. Е. Пользователь не знает об этом, кроме как путем попытки или поиска метода для установки пользовательскогоvalue
вообще.Если вы используете одно и то же соглашение во всем приложении, кажется, все в порядке.
С другой стороны, если существующая часть вашего приложения использует стандартное соглашение, я бы придерживался его и добавлял компоновщики в более сложные классы.
источник
Пауло Абрантес (Paulo Abrantes) предлагает еще один способ беглости установщиков JavaBean: определить внутренний класс построителя для каждого JavaBean. Если вы используете инструменты, которые сбиты с толку сеттерами, которые возвращают значения, шаблон Пауло может помочь.
источник
Я за сеттеров, имеющих «это» возвращение. Мне все равно, если это не бобов. Для меня, если нормально иметь выражение / оператор "=", тогда установщики, которые возвращают значения, в порядке.
источник
Раньше я предпочитал такой подход, но я решил против этого.
Причины:
Шаблон Builder, который я видел, использует не соглашение setFoo (foo) .setBar (bar), а скорее foo (foo) .bar (bar). Возможно, именно по этим причинам.
Это как всегда дело вкуса. Мне просто нравится подход "меньше всего сюрпризов".
источник
Этот конкретный шаблон называется методом цепочки. Ссылка на Википедию , здесь есть больше объяснений и примеров того, как это делается на разных языках программирования.
PS: Просто подумал оставить это здесь, так как я искал конкретное имя.
источник
На первый взгляд: «Ужасно!».
На дальнейшие мысли
на самом деле менее подвержен ошибкам, чем
Так довольно интересно. Добавление идеи в сумку с инструментами ...
источник
list
в начале нет избыточных .Да, я думаю, что это хорошая идея.
Если бы я мог добавить что-нибудь, как насчет этой проблемы:
Это будет работать:
Это не будет принято Eclipse! :
Это потому, что setName () возвращает People, а не Friend, и PeoplesetNickName отсутствует.
Как мы могли бы написать сеттеры, чтобы они возвращали класс SELF вместо имени класса?
Что-то вроде этого было бы хорошо (если бы существовало ключевое слово SELF). Это все равно существует?
источник
class C<S extends C<S>>
, который безопаснее простогоS extends C
. a) ЕслиA extends B
, иB extends C<B>
, и у вас есть A, вы знаете только, что B возвращается, если A не переопределяет каждый метод. б) Вы не можете обозначить местный, не необработанныйC<C<C<C<C<...>>>>>
.В целом, это хорошая практика, но вам может потребоваться, чтобы функции типа набора использовали логический тип, чтобы определить, успешно ли была завершена операция, это тоже один из способов. В общем, нет догмы, чтобы сказать, что это хорошо или кровать, это происходит из ситуации, конечно.
источник
Из заявления
я вижу две вещи
1) Бессмысленное утверждение. 2) Недостаток читабельности.
источник
Это может быть менее читабельным
или это
Это более читабельно, чем:
источник
Я делал свои сеттеры довольно давно, и единственная реальная проблема заключается в библиотеках, которые придерживаются строгих getPropertyDescriptors, чтобы получить средства доступа к bean-компонентам для чтения / записи bean-компонентов. В этих случаях у вашего Java-бина не будет авторов, которых вы ожидаете.
Например, я не проверял это наверняка, но я не удивлюсь, что Джексон не распознает их как сеттеры при создании ваших java-объектов из json / maps. Надеюсь, я ошибаюсь в этом (скоро опробую).
На самом деле, я разрабатываю облегченную ORM, ориентированную на SQL, и мне нужно добавить некоторый код за getPropertyDescriptors для распознанных сеттеров, который возвращает это.
источник
Давно отвечу, но мои два цента ... Хорошо. Я бы хотел, чтобы этот свободный интерфейс использовался чаще.
Повторение переменной 'factory' не добавляет дополнительной информации ниже:
Это чище, имхо:
Конечно, как уже упоминалось в одном из ответов, для некоторых ситуаций, таких как наследование и инструменты, придется настроить API Java, чтобы сделать это правильно.
источник
Лучше использовать другие языковые конструкции, если они доступны. Например, в Котлин, вы бы использовать с , применить , или пусть . Если использовать этот подход, вам не нужно возвращать экземпляр из вашего установщика.
Такой подход позволяет вашему клиентскому коду быть:
Вот несколько примеров.
источник
Если я пишу API, я использую «return this» для установки значений, которые будут установлены только один раз. Если у меня есть какие-либо другие значения, которые пользователь должен изменить, я использую вместо этого стандартный установщик пустот.
Тем не менее, это действительно вопрос предпочтений, и сеттеры, на мой взгляд, выглядят довольно круто.
источник
Я согласен со всеми авторами, утверждающими, что это нарушает спецификацию JavaBeans. Есть причины сохранить это, но я также чувствую, что использование этого паттерна строителя (на которое ссылались) имеет свое место; пока это не используется везде, это должно быть приемлемо. «Это место», для меня, где конечной точкой является вызов метода «build ()».
Конечно, есть и другие способы установки всех этих вещей, но преимущество в том, что они избегают 1) многопараметрических открытых конструкторов и 2) частично определенных объектов. Здесь у вас есть сборщик, который собирает то, что нужно, и затем вызывает его «build ()» в конце, что может гарантировать, что частично указанный объект не будет создан, так как этой операции может быть предоставлена менее публичная видимость. Альтернативой могут быть «объекты параметров», но это ИМХО просто отодвигает проблему на один уровень назад.
Мне не нравятся многопараметрические конструкторы, потому что они повышают вероятность того, что передается много аргументов одного типа, что может упростить передачу неправильных аргументов параметрам. Мне не нравится использовать множество сеттеров, потому что объект может быть использован до того, как он полностью настроен. Кроме того, понятие наличия значений по умолчанию, основанных на предыдущих вариантах, лучше использовать с помощью метода "build ()".
Короче говоря, я думаю, что это хорошая практика, если ее правильно использовать.
источник
Плохая привычка: сеттер установил геттер
как насчет явного объявления метода, который делает это для U
источник