“通过引用”编辑对象的好习惯?

Posted

技术标签:

【中文标题】“通过引用”编辑对象的好习惯?【英文标题】:Good practice to edit objects "by reference"? 【发布时间】:2011-03-16 06:41:01 【问题描述】:

假设我有一个名为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);

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

【问题讨论】:

【参考方案1】:

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

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

【讨论】:

这晚了,但是第二种方法并没有直接编辑外面的superstar。它创建superstar 的本地化版本,并且从不更改任何外部对象的属性。 @Jon 你为什么这么说?这里没有任何东西支持这种说法,不是吗?【参考方案2】:

使用方式 2,除非您正在创建一个“构建器”类,您打算在其中链接调用。例如:

MyClass c = (new MyClassBuilder()).setX(blah).setY(blah).build();

【讨论】:

您的示例完全不同,它更说明了从 setter 方法返回“this”而不是“void”以允许链接 setter 调用的想法...【参考方案3】:

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

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

【讨论】:

【参考方案4】:

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

Superstar edited = editSuperstar(originalSuperstar);

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

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

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

【讨论】:

【参考方案5】:

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

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

【讨论】:

以上是关于“通过引用”编辑对象的好习惯?的主要内容,如果未能解决你的问题,请参考以下文章

养成用Python编程写代码的好习惯

这次项目中应该注意的问题和应该保持的好习惯

Python中的好习惯或坏习惯:在文件中间导入[重复]

处理一些运行时 HTTP 异常的好习惯是啥?

这是问答的好习惯吗?

Java Reactor 中嵌套 flatMaps 的好习惯是啥?