12

假设我有一个名为Superstar. 现在我想要一个方法来完成一些工作并编辑Superstar对象的一些属性。

以下是我如何实现这一点的两种方法。方式1如下:

private Superstar editSuperstar(Superstar superstar){
    ....
    superstar.setEdited(true);
    return superstar;
}
...
superstar = editSuperstar(superstar);

方式2是这样的:

private void editSuperstar(Superstar superstar){
    ....
    superstar.setEdited(true);
}
...
editSuperstar(superstar);

这两种可能的方式中的哪一种被认为是“最佳实践”?第一个,还是第二个伪“通过引用”?

4

5 回答 5

6

在您的情况下,第二种形式更可取,因为您直接更改其中一个超级明星属性 ( edited)。但是,如果您有一个使用超级明星对象的方法并返回它的更新版本(不更改初始版本),那么第一种形式将受到我的青睐。

最后,由于这两个例子都只使用了 Superstar 对象,所以它们应该是 Superstar 类的成员方法。

于 2010-07-15T08:05:52.903 回答
4

使用方式 2,除非您正在创建一个打算链接调用的“构建器”类。前任:

MyClass c = (new MyClassBuilder()).setX(blah).setY(blah).build();
于 2010-07-15T08:06:04.983 回答
4

第一种形式具有欺骗性。它给人的印象是一个对象被传入,该对象被复制,然后该副本被更改并返回。

“最佳实践”是使用第一种形式,但实际执行隐含的操作(将更改应用于副本,然后返回)。不可变对象通常应该比可变对象更受欢迎,除非它们是大块的东西,复制起来很昂贵,在这种情况下,你应该支持第二种形式。

于 2010-07-15T08:07:24.913 回答
2

第一种方法的问题是,如果你这样使用它:

Superstar edited = editSuperstar(originalSuperstar);

这也将修改原来的Superstar,在我看来,这是违反直觉的......

因此,如果您修改传递的对象,则更喜欢第二个,如果您返回对象的新副本,则更喜欢第一个。

对于这个特殊的示例,您可以简单地向 Superstar 类添加一个编辑方法......

于 2010-07-15T08:12:00.027 回答
1

如果您返回仅更改了某些字段的相同实例,则第一种形式对于 API 客户端来说会令人惊讶。人们会期望在不更改原始实例的情况下获得修改后的副本。

因此,如果您不返回副本,请使用第二种形式,如果您这样做,请使用第一种形式(并考虑Superstar在这种情况下使不可变)。

于 2010-07-15T08:12:58.720 回答