假设我在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
对象。然而,调用构造函数或创建构建器或其他任何东西都很麻烦。因此,我希望提供此方法以方便脚本编写客户端。
答案 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());
}
}