不可改变的班级设计

时间:2010-08-01 16:23:52

标签: java

Joshua Bloch给出的建议之一是,类应该被设计为不可变的。

我有以下课程

public class Dividend {
    public Dividend setDate(SimpleDate date) {
        Dividend dividend = new Dividend(this.getStock(), this.getAmount(), date);
        return dividend;
    }
.....// More to go.

对于 setDate 方法,对象不会被修改。

相反,将返回的克隆副本及其日期字段被修改。

但是,通过判断方法名称,用户将如何知道对象仍将保持不变?

setDate 之外还有更好的命名约定吗?

6 个答案:

答案 0 :(得分:10)

如果你有setter,你的类看起来很可变,用户可能会以错误的方式使用它。他们可能会这样称呼它:

dividend.setDate(myDate);

然后惊讶为什么dividend的日期没有改变。他们应该像这样使用它:

newDividend = dividend.setDate(myDate);

为了使API更直观,最好将setDate方法重命名为copyWith

newDividend = dividend.copyWith(myDate);

或者,如果您有多个字段并且重载会令人困惑,您可以将它们称为copyWithDatecopyWithComment

其他名称也是可能的,如其他答案中所述:derive(和deriveWithDate),或只是withDate

答案 1 :(得分:3)

例如,

Font具有(a)derive方法,用于创建从当前方法派生的新字体实例。

答案 2 :(得分:2)

我见过的许多Java库开始使用with作为'此对象的副本的前缀,带有以下更改'。

例如:

public Dividend withDate() {
   ....

适合

Dividend newDividend = oldDividend.withDate(...).withAmount(...).withComment(...);
例如,

JSR-310遵循这种模式(以及使用plusXxx()minusXxx()作为“调整器”对象,例如,它取三角形而不是绝对值。

答案 3 :(得分:1)

你应该像String类一样实现你的类,它没有setter。可以理解的是,如果没有人可以在其上设置任何东西,它是不可改变的。 (也许你可能想让setter私有,或者你可能只想直接从你的Dividend类中设置变量)

答案 4 :(得分:-1)

这个函数只是构造函数的包装器。重载构造函数以接受要复制的完整被除数对象。否则,你可以重命名这个函数getDividend(它肯定不是一个setter)。

答案 5 :(得分:-1)

由于返回Dividend,用户可能会知道它是一个新的Dividend实例。即使这样,你也可以重新考虑这个名字。