Java: метод псевдо-установки для неизменяемых классов - PullRequest
13 голосов
/ 05 марта 2012

Допустим, у меня есть класс Foo в Java, в котором есть неизменяемые данные:

class Foo {
    final private int x;
    public int getX() { return this.x; }
    final private OtherStuff otherstuff;
    public Foo(int x, OtherStuff otherstuff) { 
       this.x = x;
       this.otherstuff = otherstuff;
    }   
    // lots of other stuff...
}

Теперь я хотел бы добавить вспомогательный метод, который создает значение «одноуровневое» с идентичным состоянием, но с новымзначение х.Я мог бы назвать это setX():

class Foo
{
    ...
    Foo setX(int newX) { return new Foo(newX, this.otherstuff); }
    ...
}

, но семантика setX() отличается от стандартного соглашения установщика для изменяемых объектов EJB, поэтому почему-то это не так.

Какое имя лучше для этого метода?

Должен ли я назвать его withX() или newX() или как-нибудь еще?


edit: дополнительный приоритет в моем случае: у меня есть сценарииклиенты (через JSR-223 и экспортируемую мной объектную модель), которые могут легко получить объект Foo.Однако громоздко вызывать конструкторов, создавать конструкторов или что-то еще.Поэтому для меня желательно предоставить этот метод для удобства клиентов сценариев.

Ответы [ 4 ]

13 голосов
/ 05 марта 2012

withX() звучит нормально, потому что это соглашение используется для некоторых шаблонов Builder.

Это скорее "частичный клон" или "строитель", чем "сеттер" ...

Если вы посмотрите на java.lang.String (также неизменный), есть все виды методов, которые возвращают новую строку на основе старой (substring, toLowerCase () и т. Д.) ...

Обновление : см. Также ответ от aioobe [deriveFoo()], который мне нравится - возможно, он понятнее, особенно для тех, кто не знаком с шаблонами Builder.

13 голосов
/ 05 марта 2012

Следуя стилю Font класса в стандартном API, вы бы назвали его deriveFoo(int x).

Другой вариант - предоставить класс построителя, который может приниматьFoo объект как прототип для новых объектов.В таких случаях вы обычно называете setBar() просто bar().Это даст вам что-то вроде

Foo newFoo = new Foo.Builder(foo).x(123).build();
2 голосов
/ 05 марта 2012

Я бы назвал это withX(value).Он говорит, что это будет что-то с x = value.

Если бы в классе было много полей, я бы боялся:

obj.withX(1).withY(2).withZ(3).withU(1)...

Так что я бы, возможно, использовал шаблон построителя- ввести изменяемый вариант данного класса, содержащий только данные и методы, для создания исходного класса с его текущим состоянием.И там я бы назвал эти методы x(), y(), z() и заставил бы их вернуть this.Так это будет выглядеть так:

Immutable im2 = new Mutable(im1).x(1).y(2).z(3).build();
1 голос
/ 05 марта 2012

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

public Foo newFooWith(int x) {
   return new Foo(x, other);
}

Альтернативой может быть вариант конструктора копирования

class Foo {
    public Foo(Foo foo, int x) {
      return new Foo(x, foo.getOtherStuff());
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...