Java:不可变类的伪setter方法

时间:2012-03-05 16:14:00

标签: java immutability

假设我在Java中有一个具有不可变数据的类Foo:

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...
}

现在我想添加一个实用程序方法,该方法创建一个具有相同状态但具有新值x的“兄弟”值。我可以称之为setX()

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

但是setX()的语义与可变bean对象的标准setter约定不同,所以不知怎的,这感觉不对。

这种方法的最佳名称是什么?

我应该将其称为withX()newX()还是别的?


编辑:在我的情况下的额外优先级:我有脚本客户端(通过JSR-223和我导出的对象模型),可以轻松获得Foo对象。然而,调用构造函数或创建构建器或其他任何东西都很麻烦。因此,我希望提供此方法以方便脚本编写客户端。

4 个答案:

答案 0 :(得分:13)

withX()听起来不错,因为它是一些用于某些Builder模式的约定。

这更像是“部分克隆”或“建设者”而非“制定者”...

如果你看java.lang.String(也是不可变的),有各种各样的方法可以根据旧的String返回一个新的String(substring,toLowerCase()等)......

更新:另请参阅我喜欢的 aioobe [deriveFoo()]的回答 - 它可能更清晰,特别是对那些不熟悉Builder模式的人。

答案 1 :(得分:13)

遵循标准API中Font class的样式,您可以将其称为deriveFoo(int x)

另一种选择是提供一个构建器类,它可以接受Foo对象作为新对象的原型。在这种情况下,您通常将setBar()命名为bar()。这会给你类似

的东西
Foo newFoo = new Foo.Builder(foo).x(123).build();

答案 2 :(得分:2)

我称之为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();

答案 3 :(得分:1)

它肯定是一个setter,因为它实际上构造并返回一个 new 对象。我认为在这种情况下工厂语义将是更合适的选项

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

备选方案可能是复制构造函数的变体

class Foo {
    public Foo(Foo foo, int x) {
      return new Foo(x, foo.getOtherStuff());
    }
}