Дизайн: Java и возврат самореференции в методах setter
Я уже предложил это в мой блог, но я считаю это место наиболее подходящим.
Для классов с длинным списком сеттеров, которые используются часто, я нашел этот способ очень полезным (хотя я недавно прочитал о Шаблон Builder в Эффективной Java, которая является тем же самым). В принципе, все методы setter возвращают сам объект, поэтому вы можете использовать такой код:
MyClass
.setInt(1)
.setString("test")
.setBoolean(true)
;
Сеттеры просто вернут это в конце:
public MyClass setInt(int anInt) {
[snip]
return this;
}
Каково ваше мнение? Каковы плюсы и минусы? Это влияет на производительность?
Ответы
Ответ 1
@pek
Цепной вызов является одним из предложений для Java 7. В нем говорится, что если тип возвращаемого метода недействителен, он должен неявно возвращать этот. Если вас интересует эта тема, есть куча ссылок и простой пример на странице Alex Miller Java 7.
Ответ 2
Это называется Fluent Interface для справки.
Лично я думаю, что это довольно аккуратная идея, но дело вкуса действительно. Я думаю, jQuery работает таким образом.
Ответ 3
Я бы не стал делать это сам, потому что для меня это мешает то, что делает какой-то конкретный метод, и метод-цепочка имеет ограниченное применение для меня, делая это заново. Это не собирается посылать меня в дрожащий шар ярости и психоза, хотя, что всегда хорошо.: ')
Меня бы не беспокоило производительность; просто спросите Кнута.
Ответ 4
Я считаю, что это плохой стиль при использовании в сеттерах. Неизменяемые классы обычно лучше подходят для цепочки, например:
aWithB = myObject.withA(someA).withB(someB);
где myObject
принадлежит этому классу:
class MyClass {
withA(TypeA a) {
this.a.equals(a) ? this : new MyClass(this, a);
}
private MyClass(MyClass copy, TypeA a) {
this(copy);
this.a = a;
}
}
Шаблон построителя также полезен, поскольку он позволяет окончательному объекту быть неизменным, предотвращая промежуточные экземпляры, которые вы обычно должны создавать при использовании этой техники.
Ответ 5
Это имеет смысл для строителей, где все, что вы собираетесь делать, это установить нагрузку, создать реальный объект и выбросить строитель. Для строителей вы также можете избавиться от "установленной" части имени метода. Точно так же неизменяемым типам действительно не нужно "получать".
Something thing = new SomethingBuilder()
.aProperty(wotsit)
.anotherProperty(somethingElse)
.create();
Полезный трюк (если вы не возражаете, что накладные расходы на время выполнения 2K для каждого класса) заключается в использовании идиомы двойной привязки:
JFrame frame = new JFrame("My frame") {{
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setLocation(frameTopLeft);
add(createContents());
pack();
setVisible(true);
}};
Ответ 6
Эта идея много видна в С++, она позволяет выполнять каскадные операции...
например
std::cout << "this" << "is" << "cascading"
где метод потока < возвращает экземпляр самого себя (* this).
см. это: http://www.java2s.com/Tutorial/Cpp/0180__Class/Cascadingmemberfunctioncallswiththethispointer.htm
Ответ 7
Я использую, чтобы быть поклонником практики Java (и хуже С#) создания геттеров и сеттеров (получить заданные свойства) по всему объекту. Это использование должно быть тем, что я рассматривал как объектно-ориентированное, но на самом деле это приводит нас к тому, чтобы разоблачать кишки и реализацию объекта, а не использовать инкапсуляцию. Иногда вы не можете уйти от этого (OR/M приходит на ум), но в целом объект должен быть настроен, а затем выполнять свою функцию. Объекты моей мечты имеют один или два конструктора и, возможно, полдюжины функций, которые работают.
Причиной этого является то, что, как только я начал разрабатывать API, существует настоятельная необходимость держать вещи простыми. Вы действительно хотите добавить столько же сложности, сколько требуется для выполнения работы, а также для геттеров и сеттеров, хотя и простых по себе, добавляя сложность в кучи при добавлении в массе. Что происходит, когда я загружаю сеттеры в другой порядок? Любое другое? Вы уверены?
Ответ 8
@Повторите еще раз для более сложных ситуаций (неизменность имеет в виду) шаблон Builder - отличное решение.
Кроме того, я согласен с вами в основном в геттерах. Я считаю, что вы говорите, что в основном следуете " Tell do not ask" парадигма, и я очень согласен. Но это ориентировано в основном на геттеры.
Наконец, все вышеперечисленное относится к классам с большим количеством атрибутов. Я не вижу причины, если у вас меньше, чем, скажем, 7.
Ответ 9
В итоге я много работал над работой с библиотекой Apache POI excel; Я закончил писать вспомогательные методы, которые были привязаны, поэтому я мог применять форматирование, типы данных, внутренние данные ячеек, формулы и позиционирование ячейки.
Для вещей с множеством маленьких крошечных элементов мухи, которые должны иметь небольшие хитрости, он работает очень хорошо.
Ответ 10
Как использовать
/**
*
* @author sanjay
*/
public class NewClass {
private int left ;
private int top;
public void set(int x,int y)
{
left=x;
top=y;
}
public NewClass UP(int x)
{
top+=x;
return this;
}
public NewClass DOWN(int x)
{
top-=x;
return this;
}
public NewClass RIGHT(int x)
{
left+=x;
return this;
}
public NewClass LEFT(int x)
{
left-=x;
return this;
}
public void Display()
{
System.out.println("TOP:"+top);
System.out.println("\nLEFT\n:"+left);
}
}
public static void main(String[] args) {
// TODO code application logic here
NewClass test = new NewClass();
test.set(0,0);
test.Display();
test.UP(20).UP(45).DOWN(12).RIGHT(32).LEFT(20);
test.Display();
Ответ 11
Я согласен с @Bernard, что метод цепочки, подобный этому, путает цель сеттеров. Вместо этого я бы предположил, что если вы всегда создаете такие сеттеры, как это, вы создаете собственный конструктор для своего класса, а вместо
MyClass
.setInt(1)
.setString("test")
.setBoolean(true)
;
Вы делаете
new MyClass(1,"test",true);
Это делает его более читаемым, и вы можете использовать его, чтобы сделать ваш класс неизменным, если вы решили.