Это плохая практика, чтобы заставить сеттер возвращать «это»?

Это хорошая или плохая идея сделать возвращение сеттеров в Java? "этот"?

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 для создания объектов.

 Pino05 апр. 2019 г., 14:37
Смотрите такжеstackoverflow.com/questions/5741369/...
 oᴉɹǝɥɔ14 дек. 2016 г., 03:52
Для телескопических сеттеров, возвращающих себя и в конструкторах, я предпочитаю использовать withName (имя строки) вместо setName (имя строки). Как вы указали, обычной практикой и ожиданием сеттера является возврат void. "Нестандартные» сеттеры могут плохо работать с существующими фреймворками, например Менеджеры сущностей JPA, Spring и др.
 Legna08 авг. 2017 г., 23:01
Широко используемые фреймворки (например, Spring и Hibernate) будут строго (по крайней мере, раньше) придерживаться соглашения void-setters
 MauganRa23 февр. 2017 г., 19:59
Пожалуйста, вводите разрывы строк перед каждым вызовом :) И настройте свою IDE или получите подходящую, если это не так.не уважаю это.
 Inversus17 апр. 2014 г., 11:42
Так как я'Я видел этот шаблон дизайна некоторое время назад, я делаю это везде, где это возможно. Если метод неТ явно нужно вернуть что-то, чтобы сделать свою работу, теперь он возвращаетthis, Иногда я даже изменяю функцию так, чтобы вместо возврата значения она работала с членом объекта, просто чтобы я мог это сделать. Это'это замечательно. :)

Ответы на вопрос(27)

Я согласен со всеми авторами, утверждающими, что это нарушает спецификацию JavaBeans. Есть причины сохранить это, но я также чувствую, что использование этого паттерна строителя (на которое ссылались) имеет свое место; пока это не используется везде, это должно быть приемлемо. "Это's Place "для меня, где конечной точкой является вызов "строить ()» метод.

Конечно, есть и другие способы установки всех этих вещей, но преимущество в том, что они избегают 1) многопараметрических открытых конструкторов и 2) частично определенных объектов. Здесь у вас есть строитель собирать чтоНужно и потом назови егостроить ()» в конце, который может гарантировать, что частично указанный объект не будет создан, так как этой операции может быть предоставлена менее публичная видимость. Альтернатива будетпараметры объекта ", но это ИМХО просто отталкивает проблему на один уровень назад.

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

Короче говоря, я думаю, что это хорошая практика, если ее использовать правильно.

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

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

Это'Также распространены в Java API:

String s = new StringBuilder().append("testing ").append(1)
  .append(" 2 ").append(3).toString();
 cletus28 авг. 2009 г., 06:45
Вероятно, окончательное воплощение беглых интерфейсов - это LINQ.
 Wayne Conrad02 февр. 2011 г., 07:01
@ddimitrov - шаблон строителя, хотя он выглядит так же, каккрушение поезда," не нарушает закон Деметры. Это действительно крушение поезда?
 Stefan24 окт. 2012 г., 22:24
@ddimitrov пока вы ограничиваетесь возвращениемэтот это никогда не будет проблемой (только первое обращение может бросить NPE)
 Thorbjørn Ravn Andersen12 февр. 2014 г., 16:38
@BrentNash Я считаю, что реальное обоснование не так много, как облегчение кодачитать но это облегчаетзаписывать и поэтому авторы предпочитают его и неявно считают, что его легче читать.
 Laurence Gonsalves28 авг. 2009 г., 06:31
Это'частоиспользуемый в строителей, но я бы несказать "это ... называется шаблоном Builder ".
 ddimitrov02 мар. 2010 г., 15:49
Это's также известен как антипаттерн крушения поезда. Проблема в том, что когда трассировка стека исключений с нулевым указателем содержит строку, подобную этой, вы не представляете, какой вызов вернул null. Тот'Нельзя сказать, что цепочки следует избегать любой ценой, но остерегайтесь плохих библиотек (особенно домашних).
 Brent Writes Code28 авг. 2009 г., 06:36
Это'Мне смешно, что некоторые из оснований для свободных интерфейсов в том, что они делают код легче для чтения. Я мог видеть, что писать удобнее, но мне кажется, что читать сложнее. Тот'Это единственное настоящее несогласие с этим.
 MauganRa23 февр. 2017 г., 19:51
@AndreasDietrich также, это позволяет пройти через "поезд" с отладчиком :-D
 ddimitrov02 февр. 2011 г., 16:37
@ Уэйн Конрад - закон Деметры здесь не имеет значения (мыне говорим о посредниках) - если он бросает NPE, вы выигралине знаю, какое утверждение вызвало это и чтосидеть. Есть много хороших примеров связанного APIs (Easymock / Mockito приходит на ум), но ямы тоже видели довольно ужасные мерзости, и их трудно отлаживать и поддерживать.
 Charles Wood03 мар. 2017 г., 22:33
Легко читать зависит от человека. Тот'почему у нас так много разных моделей;)
 Andreas Dietrich06 февр. 2015 г., 22:48
Это'проще писать и читать Предполагается, что вы ставите переносы и отступы там, где читаемость пострадает в противном случае! (потому что это избегает избыточного беспорядка повторяющегося кода какbla.foo.setBar1(...) ; bla.foo.setBar2(...) когда ты мог написатьbla.foo /* newline indented */.setBar1(...) /* underneath previous setter */ .setBar2(...) (Можно'не используйте разрывы строк в комментариях SO, как это :-( ... надеюсь, вы получите точку зрения, учитывая 10 таких сеттеров или более сложные вызовы)

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

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); 
 Ken Liu20 мая 2010 г., 20:05
Я думаю это'довольно читабелен, если вы нене пытайтесь поместить весь ваш код в одну строку.

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

 cdunn200114 дек. 2011 г., 17:09
буду upvote, но ваша ссылка не работает.
 msangel05 янв. 2014 г., 19:52

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

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

Повторяязавод» Переменная не добавляет больше информации ниже:

ProxyFactory factory = new ProxyFactory();
factory.setSuperclass(Foo.class);
factory.setFilter(new MethodFilter() { ...

Это чище, имхо:

ProxyFactory factory = new ProxyFactory()
.setSuperclass(Properties.class);
.setFilter(new MethodFilter() { ...

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

Я предпочитаю использоватьс' методы для этого:

public String getFoo() { return foo; }
public void setFoo(String foo) { this.foo = foo; }
public Employee withFoo(String foo) {
  setFoo(foo);
  return this;
}

Таким образом:

list.add(new Employee().withName("Jack Sparrow")
                       .withId(1)
                       .withFoo("bacon!"));
 AlikElzin-kilaka01 июл. 2013 г., 13:27
Кроме того, можете ли вы указать на некоторые популярные библиотеки, использующие этот шаблон?
 qualidafial20 янв. 2015 г., 18:14
Согласовано. Пожалуйста, перечитайте мой комментарий, я рекомендовал включить метод with, который возвращает тип self, в дополнение к методам get и set.
 Emerald Hieu19 янв. 2015 г., 07:28
Что если Java Bean является сущностью? "задавать", "получить" Префиксы не могут быть опущены, потому что они являются соглашением об именах.
 Andreas Dietrich07 февр. 2015 г., 13:36
Классная основная идея. У меня были проблемы с сериализацией GWT AutoBeans (de) с использованием беглых методов здесь, и я в основном буду использовать вашу идею в будущем таким образом (чтоближе - также визуально / для автозаполнения и т. д. - к обычным методам):void setFoo(Foo foo); Employee setFoo$(Foo foo) (with Безразлично»мне кажется, это не лучшая идея для доводов "против"
 qualidafial03 июл. 2013 г., 17:36
@kilaka Спасибо, я исправил тип возврата. Что касается твоего вопроса, с головы до головы, я неНе знаю ни одной популярной библиотеки, которая использует этот шаблон.
 qualidafial11 февр. 2015 г., 17:30
@ AlikElzin-kilaka На самом деле я только что заметил, что неизменяемые классы java.time в Java 8 используют этот шаблон, например, LocalDate.withMonth, withYear и т. Д.
 qualidafial24 окт. 2011 г., 22:55
Это зависит от того, как часто вы вызываете сеттеров. Я'мы обнаружили, что если этих сеттеров часто вызывают,Стоит добавить лишних хлопот, так как это упрощает код везде. YMMV
 Ehtesh Choudhury28 мар. 2012 г., 21:18
И если вы добавили это кProject Lombok@Getter/@Setter аннотации ... это "буду фантастическим для цепочки. Или вы можете использовать что-то похожее наKestrel комбинатор (github.com/raganwald/Katy), которые используют изверги JQuery и Javascript.
 Logikos13 янв. 2018 г., 15:53
with префикс это другое соглашение. как @qualidafial привел пример. методы с префиксомwith не должен возвращатьсяthis а скорее новый экземпляр, как текущий экземпляр, ноwith это изменение. Это делается, когда вы хотите, чтобы ваши объекты были неизменными. Поэтому, когда я вижу метод с префиксомwith Я полагаюЯ получу новый объект, а не тот же объект.
 Paul Manta21 июн. 2011 г., 22:44
+1 За интересное соглашение. Я'Я не собираюсь принимать его в моем собственном коде, так как кажется, что теперь вы должны иметьget,set иwith для каждого поля класса. Это'Это все еще интересное решение. :)
 AlikElzin-kilaka01 июл. 2013 г., 13:26
@qualidafial - я думаю, что тамошибка в коде withFoo (...) должен объявить Employee как возвращаемое значение, а не String.

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

 Narek15 нояб. 2017 г., 18:09
Исключения обычно предпочтительнее, но коды ошибок также полезны, когда вы можетеиспользовать исключения.
 ddimitrov16 янв. 2018 г., 09:37
Привет @Narek, возможно, вы могли бы уточнить, в каких случаях предпочтительнее использовать коды ошибок в установщиках, а не в исключениях, и почему?
 ddimitrov02 мар. 2010 г., 15:59
Как насчет использования исключений для обозначения состояния ошибки? Коды ошибок можно легко проигнорировать, как мучительно усвоили многие программисты на Си. Исключения могут пузырить стек до точки, где они могут быть обработаны.

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

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

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

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

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

 DJDaveMark16 янв. 2019 г., 09:39
@qualidafial Вы нене нужно// после каждого метода, если вы настраиваете свою среду IDE, чтобы не объединять уже перенесенные строки (например, Eclipse> Свойства> Java> Стиль кода> Форматер> Обтекание строк> Никогда не присоединяйся к уже обернутым линиям).
 Carson Myers29 авг. 2009 г., 02:21
вы''вероятно, прав ... Единственный автоформатер, который я использовал, это emacs' Авто отступ.
 Thorbjørn Ravn Andersen28 авг. 2009 г., 08:13
"даже лучше" не подходит для функциональности Format Source code, доступной в современной IDE 's. К несчастью.
 qualidafial20 дек. 2010 г., 20:40
Форматировщики исходного кода можно принудительно вводить с помощью простого // после каждого вызова метода в цепочке. Это немного портит ваш код, но не так сильно, потому что ваш вертикальный ряд операторов переформатирован горизонтально.

Подвести итоги:

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

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

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

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

Я наконец-то здесьЭто реальная точка данных. У меня были проблемы с использованием библиотеки, созданной следующим образом. спящий режим»s построитель запросов является примером этого в существующей библиотеке. Так как Query 's set * методы возвращают запросы, это 'Невозможно сказать, просто взглянув на подпись, как ее использовать. Например:

Query setWhatever(String what);

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

 Marton_hun19 мая 2018 г., 14:48
дополнительный пункт: это также нарушает Команду -принцип разделения запросов.
 user94930030 окт. 2016 г., 02:54
Хотя я согласен в целом, я не согласен, что это нарушаетделать только одно " главный. возвратеthis вряд ли сложная ракетостроение. :-)
 Ken Liu03 сент. 2009 г., 14:29
Кстати, это "свободно»нежидкость»... так как он позволяет структурировать серию вызовов методов, как разговорный язык.
 MeTTeO19 сент. 2015 г., 11:21
Последний пункт об неизменности очень важен. Самый простой пример - String. Разработчики Java ожидают, что при использовании методов в String они получают совершенно новый экземпляр, а не тот же, но измененный экземпляр. При свободном интерфейсе в документации метода должно быть упомянуто, что возвращаемый объектэтот' вместо нового экземпляра.
 Yousha Aleayoub06 сент. 2016 г., 03:06
ЭТО должно быть принято, а не над ответами ...

Я делал свои сеттеры довольно давно, и единственная реальная проблема заключается в библиотеках, которые придерживаются строгих getPropertyDescriptors, чтобы получить средства доступа к bean-компонентам. В этих случаях твоя явабоб» не будет авторов, которых вы ожидаете.

Например, я не проверял это наверняка, но я не удивлюсь, что Джексон выиграл.t распознает их как сеттеры при создании ваших java-объектов из json / maps. Надеюсь, я ошибаюсь в этом (скоро опробую).

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

Да, я думаю этохорошая идея

Если бы я мог добавить что-нибудь, как насчет этой проблемы:

class People
{
    private String name;
    public People setName(String name)
    {
        this.name = name;
        return this;
    }
}

class Friend extends People
{
    private String nickName;
    public Friend setNickName(String nickName)
    {
        this.nickName = nickName;
        return this;
    }
}

Это будет работать:

new Friend().setNickName("Bart").setName("Barthelemy");

Это не будет принято Eclipse! :

new Friend().setName("Barthelemy").setNickName("Bart");

Это потому, что setName () возвращает People, а не Friend, и PeoplesetNickName отсутствует.

Как мы могли бы написать сеттеры, чтобы они возвращали класс SELF вместо имени класса?

Что-то вроде этого было бы хорошо (если бы существовало ключевое слово SELF). Это все равно существует?

class People
{
    private String name;
    public SELF setName(String name)
    {
        this.name = name;
        return this;
    }
}
 Ajax01 февр. 2013 г., 16:17
Используйте дженерики. класс Chainable <Self расширяет Chainable> {public Self doSomething () {return (Self) this;}} Это 'технически не безопасен с точки зрения типов (класс будет приведен к классу, если вы реализуете класс с типом Self, который не может быть регистром), но это правильная грамматика, и подклассы будут возвращать свой собственный тип.
 Cornel Masson04 июн. 2012 г., 11:39
Помимо Eclipse, есть несколько других Java-компиляторов, которые выиграли 'не принимаю это :). По сути, выповторное использование системы типов Java (которая является статической, а не динамической, как некоторые языки сценариев): вы 'Придется разыграть то, что выходит из setName () другу, прежде чем вы сможете установить для него setNickName (). Так что, к сожалению, для иерархий наследования это устраняет большую часть преимуществ читабельности и делает эту потенциально потенциально полезную технику не очень полезной.
 Adowrath19 авг. 2017 г., 21:49
Кроме того: это "SELF» то, что использует Баптист, называется типом self, которого нет во многих языках (Scala - действительно единственный, о котором я могу думать сейчас), где как Ajax 'с использованием дженериков является так называемымЛюбопытно повторяющийся шаблон ", который пытается справиться с отсутствием типа личности, но это 'Есть некоторые недостатки: (отclass C, который безопаснее равниныS extends C, а) еслиA extends B, а такжеB extends Cи у вас есть A, вы знаете только, что B возвращается, если A не переопределяет каждый метод. б) Вы можетет обозначает местный, необработанный.C

На первый взгляд: "Жуть!».

На дальнейшие мысли

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

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

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

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

 Ken Liu28 авг. 2009 г., 06:53
лично я думаю, что первое легче читать, особенно если вы создаете несколько объектов таким образом.
 MauganRa23 февр. 2017 г., 19:53
Было бы хорошо, если бы перед каждой точкой и отступом были разрывы строк. Затем это'будет так же читабельно, как и вторая версия. На самом деле больше, потому что нет лишнихlist в начале.
 OMG Ponies28 авг. 2009 г., 06:57
@ Кен: код метода. Написать одну копию в свободном формате; другой экземпляр в другом. Теперь дайте две копии нескольким людям и спросите, какую из них они находят более удобной для чтения. Быстрее читать, быстрее кодировать.
 staticsan28 авг. 2009 г., 07:18
Как и большинство инструментов, его легко использовать. JQuery ориентирован на эту технику и поэтому склонен к длинным цепочкам вызовов, которые яМы обнаружили, что на самом деле ухудшает читабельность.
 OMG Ponies28 авг. 2009 г., 06:52
Нет этовсе еще ужасно. С точки зрения технического обслуживания, последний лучше, потому чтолегче читать. Кроме того, автоматические средства проверки кода, такие как CheckStyle, принудительно заставят строки по умолчанию составлять 80 символов - в любом случае код будет перенесен, что усугубит проблему читаемости / сопровождения. И наконец - этос Java; там'нет смысла писать все в одной строке, когда этоВсе равно будет скомпилировано в байт-код.

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

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

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

list.Add(new Employee() {
    Name = "Jack Sparrow",
    Id = 1,
    Foo = "bacon!"
});
 Andreas Dietrich24 февр. 2017 г., 09:56
работает только дляновый объекты хотя!
 MauganRa23 февр. 2017 г., 19:57
Это мой новый любимый сейчас, спасибо! :)
 Csaba_H28 авг. 2009 г., 07:59
инициализация двойной скобки может иметь проблемы с equals, потому что она создает анонимный внутренний класс; увидетьc2.com/cgi/wiki?DoubleBraceInitialization
 AJMansfield24 янв. 2014 г., 21:07
@ Csaba_H Ясно, что эта проблема - ошибка человека, которыйequals метод. Есть очень чистые способы иметь дело с анонимными классами вequals если ты знаешь, что делаешь.

Если я'я пишу API, я используюверни это " установить значения, которые будут установлены только один раз. Если у меня есть какие-либо другие значения, которые пользователь может изменить, я использую вместо этого стандартный установщик пустот.

Тем не менее, это 'Это действительно вопрос предпочтений, и сеттеры, на мой взгляд, выглядят довольно круто.

Это'это совсем не плохая практика. Но это'не совместимы сJavaBeans Spec.

И много спецификаций зависит от этих стандартных средств доступа.

Вы всегда можете заставить их сосуществовать друг с другом.

public class Some {
    public String getValue() { // JavaBeans
        return value;
    }
    public void setValue(final String value) { // JavaBeans
        this.value = value;
    }
    public String value() { // simple
        return getValue();
    }
    public Some value(final String value) { // fluent/chaining
        setValue(value);
        return this;
    }
    private String value;
}

Теперь мы можем использовать их вместе.

new Some().value("some").getValue();

Вот еще одна версия для неизменного объекта.

public class Some {

    public static class Builder {

        public Some build() { return new Some(value); }

        public Builder value(final String value) {
            this.value = value;
            return this;
        }

        private String value;
    }

    private Some(final String value) {
        super();
        this.value = value;
    }

    public String getValue() { return value; }

    public String value() { return getValue();}

    private final String value;
}

Теперь мы можем сделать это.

new Some.Builder().value("value").build().getValue();
 Jin Kwon18 авг. 2017 г., 03:42
@ Adowrath Я только что обновил свой ответ.
 Adowrath18 авг. 2017 г., 07:56
@JinKwon Отлично. Спасибо! И извините, если я казался грубым раньше.
 CalvT03 авг. 2017 г., 13:37
@ Adowrath, если ответ неправильный, вы должны написать свой собственный ответ, а не пытаться редактировать кого-то другого »в форме
 Adowrath03 авг. 2017 г., 13:49
@CalvT 븃Таким образом, я должен оставить неправильную информацию там, когда это просто нужно немного редактировать? Это'нередактирование в форму ", но исправляя небольшие ошибки, которые он сделал. Кроме того, его пример Builder является расширением нормального ответа и не потребует от меня совершенно собственного ответа.
 Jin Kwon18 авг. 2017 г., 08:01
@ Adowrath Пожалуйста, не стесняйтесь любые дополнительные комментарии для улучшений. К вашему сведениюя не тот, кто отклонил вашу правку. :)
 Adowrath19 авг. 2017 г., 00:12
Я знаю я знаю. ^^ И спасибо за новую версию, которая теперь обеспечивает настоящую изменчивость "Неизменная-Some» строитель. И это'Это более умное решение, чем мои попытки редактирования, которые, по сравнению, загромождали код.
 Adowrath30 мар. 2017 г., 22:12
Мое редактирование отклонено, но ваш пример Builder неверен. Во-первых, .value () ничего не возвращает и нет даже установитьsome поле. Во-вторых, вы должны добавить защиту и установитьsome вnull в build () такSome действительно неизменный, иначе вы могли бы позвонитьbuilder.value() снова на том же экземпляре Builder. И, наконец, да, у вас есть строитель, но вашSome все еще имеет общедоступный конструктор, то есть вы открыто не защищаете использование Builder, т. е. пользователь не знает об этом, кроме как путем попытки или поиска метода для установки пользовательскогоvalue совсем.

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

С другой стороны, если существующая часть вашего приложения использует стандартное соглашение I 'буду придерживаться этого и добавлять строителей в более сложные классы

public class NutritionalFacts {
    private final int sodium;
    private final int fat;
    private final int carbo;

    public int getSodium(){
        return sodium;
    }

    public int getfat(){
        return fat;
    }

    public int getCarbo(){
        return carbo;
    }

    public static class Builder {
        private int sodium;
        private int fat;
        private int carbo;

        public Builder sodium(int s) {
            this.sodium = s;
            return this;
        }

        public Builder fat(int f) {
            this.fat = f;
            return this;
        }

        public Builder carbo(int c) {
            this.carbo = c;
            return this;
        }

        public NutritionalFacts build() {
            return new NutritionalFacts(this);
        }
    }

    private NutritionalFacts(Builder b) {
        this.sodium = b.sodium;
        this.fat = b.fat;
        this.carbo = b.carbo;
    }
}
 ndm1329 дек. 2017 г., 21:26
Это именно то, что шаблон Builder был разработан, чтобы исправить. Это нене ломать лямбды в Java 8, это нене ломать привередливые инструменты JavaBeans, и это неt вызвать какие-либо проблемы оптимизации в JVM (поскольку объект существует только во время создания экземпляра). Это также решаетслишком много конструкторов " проблема, которую вы получаете, просто не используя компоновщики, а также устраняя загрязнение кучи из двойных анонимных классов.

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

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

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

Плохая привычка: сеттер установил геттер

как насчет явного объявления метода, который делает это для U

setPropertyFromParams(array $hashParamList) { ... }
 Andreas Dietrich24 февр. 2017 г., 10:13
не подходит для автозаполнения, рефакторинга и читабельности и стандартного кода
 Adowrath29 мар. 2017 г., 19:14
Потому что: 1) Вы должны помнить порядок или читать его из документов, 2) вы теряете всю безопасность типов во время компиляции, 3) вы должны приводить значения (это и 2), конечно, не проблема в динамическом язык конечно), 4) можноне расширять это полезно, кроме проверки длины массива при каждом вызове, и 5)если Вы можете изменить что-либо, будь то порядок или даже существование определенных ценностей, вы можетене проверьте, что ни время выполнения, ни время компиляции без сомненийсовсем, С сеттерами: 1), 2), 3): не проблема. 4) Добавление новых методов ничего не нарушает. 5) явное сообщение об ошибке.

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

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

Тот'почему я голосую нет, нене используй это.

 Marian28 авг. 2009 г., 23:51
Подумайте, как суперскалярные процессоры справляются с параллельным выполнением. Объект для выполнения второгоset метод зависит от первогоset метод, хотя это известно программисту.
 Carson Myers28 авг. 2009 г., 07:06
Согласен, яХотелось бы узнать больше о том, как это может повлиять на оптимизацию
 Ajax01 февр. 2013 г., 16:11
Если вы нене знаю, проверить.-XX:+UnlockDiagnosticVMOptions -XX:+PrintInlining    Java7 jdk однозначно встраивает цепочечные методы и делает примерно такое же количество итераций, которое требуется, чтобы пометить пустые сеттеры как горячие и встроить их тоже. Мне кажется, вы недооцениваете силу JVMалгоритмы сокращения кода операции; если он знает, что вы возвращаете это, он пропустит код операции jrs (оператор возврата java) и просто оставит его в стеке.
 Ken Liu28 авг. 2009 г., 06:51
Интересно ... не могли бы вы рассказать об этом немного?
 Thomas Eding09 авг. 2011 г., 02:46
@masonk: Возможно, что-то вроде этого:obj.modifyList(aList).modifyList(anotherList), гдеmodifyList не модифицируетthisеще нужно знать чтоthis является.
 LegendLength14 июл. 2017 г., 22:01
Андреас, я согласен, но проблемы возникают, когда у вас слой за слоем неэффективного кода. 99% времени вы должны писать для ясности, о чем здесь много говорят. Но бывают случаи, когда вам нужно быть реалистами и использовать свой многолетний опыт, чтобы преждевременно оптимизировать в общем архитектурном смысле.
 masonk27 февр. 2011 г., 02:18
Я до сих пор нет следовать. Если вы установите Foo, а затем Bar с двумя отдельными операторами, объект, для которого вы 'Повторная настройка Бар имеет другое состояние, чем объект, для которого выпереустановить Foo. Так что компилятор не мограспараллелить эти утверждения, либо. По крайней мере, я неЯ не вижу, как это могло бы произойти без введения необоснованного предположения. (Поскольку я понятия не имею об этом, я выиграл 'отрицать, что Java 43 фактически выполняет распараллеливание в одном случае, но не в другом, и вводит необоснованное предположение в одном случае, но не во втором).
 Andreas Dietrich24 февр. 2017 г., 10:06
Но нужно действительно подумать, является ли оптимизация проблемой для его кода. Почти весь код, который я написал в своей карьере, должен был быть не слишком быстрым, а скорее понятным и безошибочным. Таким образом, я бы сказал, что большинство кодов / кодеров не должны быть чрезвычайно озабочены скоростью, а не удобством обслуживания, которое также включает удобочитаемость. Сама Java - очень хороший пример того, что это был один из самых медленных языков. несколько лет назад, но все же был принят почти везде, потому что скорость будет вкл. на твердой и мягкой стороне в любом случае, но ремонтопригодность гораздо важнее.
Решение Вопроса

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

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

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

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

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

 Andy White28 авг. 2009 г., 06:57
@ Хороший момент, это нарушает "Боб " соглашение для добытчиков и сеттеров.
 Christian Bongiorno20 авг. 2018 г., 23:55
возвратеthis имеет основополагающее значение дляBuilder шаблон. Но, возвращаясьthis Кроме того, по замыслу операция с состоянием. Не существует универсального подхода. Пользуйся неизменностью. Весь смысл строителя (обычно) состоит в том, чтобы сделать неизменный объект надежным
 RicardoE18 апр. 2015 г., 00:45
именно поэтому шаблон Builder существует, сеттеры не должны возвращать что-то, вместо этого создавать конструктор, если он нужен, выглядит лучше и требует меньше кода :)
 vaso12308 мар. 2017 г., 14:01
Для меня этоs, кажется, имя функции лежит, если я возвращаюсь с чем-либо. Если оно's возвращается с объектом, тогда имя этого должно бытьsetPropertyAndGetObject(); Set имеет одну вещь, чтобы установить свойство. Конечно, мне не нужно знать, как сеттер реализует этот набор, например$A->setFullName($firstName, $lastName); Можно сделать некоторую логику, например, в разных странах фамилия является первым, а имя является вторым. Но это делает только одно: устанавливает полное имя.
 Bimalesh Jha07 июл. 2016 г., 16:55
Вы можете иметь специальный установщик, который может взять карту свойств (имя и значения). Затем внутри метода вы можете использовать отражение, чтобы вызвать соответствующие установщики. Этот подход может не работать, если у вас есть несколько перегруженных сеттеров, и преимущество проверки времени компиляции также теряется.
 Theo Briscoe05 дек. 2013 г., 15:30
@TomClift делает взлом "Java Bean " Конвенция вызывает какие-либо проблемы? Являются ли библиотеки, которые используют "Java Bean " соглашение о типе возвращаемого значения или просто параметрах метода и имени метода.
 Ken Liu28 авг. 2009 г., 06:39
ну вообще ты нев любом случае, ничего не вернуть от сеттера.
 Tom Clift28 авг. 2009 г., 06:54
Может быть, не для начала, но сеттер нет обязательно сохранить свое первоначальное назначение. То, что раньше было переменной, может измениться в состояние, которое охватывает несколько переменных или иметь другие побочные эффекты. Некоторые установщики могут возвращать предыдущее значение, другие могут возвращать индикатор сбоя, если сбой слишком распространен для исключения. Это поднимает еще один интересный момент: что делать, если инструмент / рамки выповторное использование нераспознавать ваши сеттеры, когда они возвращают значения?
 Andreas Dietrich06 февр. 2015 г., 22:41
к сожалению, я работаю в среде, ориентированной на данные (DTO, DAO), и теперь яМожно'т выгоду отAutoBean (code.google.com/p/google-web-toolkit/wiki/AutoBean#Quickstart) функциональность, которая можетсправиться с этим нестандартным бобом "из коробки", Так что я боюсьпотерять преимущество меньшего количества стандартного кода здесь :-(. Но, может быть, есть способ с этим ... Яя увижу.
 inigoD15 февр. 2018 г., 11:03
@ vaso123 Я чувствую твою боль ... Но если альтернатива состоит в том, чтобы иметь мега-конструктор, я могу с этим смириться ... В любом случае, твой пример мне не так понятен: когда ты, я или кто-то еще слышишь о 'сеттер' думает одобытчики и сеттерыи не орассчитать правильную стратегию, чтобы создать значение и установить его »: Ваш пример должен быть: setFullName (calcFullName (firstName, lastName)). Для меня, имея в своем уме «Сеттеры и Геттеры» четкое определение, вопрос должен звучать так: будет ли факт возвращения »этот' в сеттере изменить это определение драматическим образом?

Лучше использовать другие языковые конструкции, если они доступны. Например, в Kotlin, вы бы использовалис,применять, или жепозволять, Если использовать этот подход, вы выигралиправданеобходимость вернуть экземпляр из вашего сеттера.

Такой подход позволяет вашему клиентскому коду быть:

Безразличен к типу возвратаПроще поддерживатьИзбегайте побочных эффектов компилятора

Вот несколько примеров.

val employee = Employee().apply {
   name = "Jack Sparrow"
   id = 1
   foo = "bacon"
}


val employee = Employee()
with(employee) {
   name = "Jack Sparrow"
   id = 1
   foo = "bacon"
}


val employee = Employee()
employee.let {
   it.name = "Jack Sparrow"
   it.id = 1
   it.foo = "bacon"
}

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

Причины:

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

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

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

 crunchdog28 авг. 2009 г., 07:52
Я согласен на побочный эффект. Сеттеры, которые возвращают вещи, нарушают их имя. Вы настраиваете foo, но получаете объект обратно? Это новый объект или я изменил старый?

Он не только нарушает соглашение о методах получения / установки, но также нарушает структуру ссылок на методы Java 8.MyClass::setMyValue этоBiConsumer, а такжеmyInstance::setMyValue этоConsumer, Если у вас есть возвращение сеттераthis, Затем это'больше не является действительным экземпляромConsumer, а скорееFunctionи приведет к тому, что что-либо, использующее ссылки на методы к этим установщикам (при условии, что они являются пустыми методами), сломается

 Adowrath29 мар. 2017 г., 19:17
Было бы здорово, если бы у Java был какой-то способ перегрузки по типу возвращаемого значения, а не только по JVM. Вы можете легко обойти многие из этих критических изменений.

Из заявления

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

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

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

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

 ddimitrov02 мар. 2010 г., 15:54
Это также имеет значение, если вы используете бин-ориентированные фреймворки, такие как Spring.
 Dan Vinton20 мая 2010 г., 16:36
или если вы используете API интроспекции для написания рефлексивного кода ...

Ваш ответ на вопрос