Java 不变类设计

Java 不变类设计,java,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. 对于se

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还有更好的命名约定吗?

如果您有setter,您的类将看起来是可变的,用户可能会错误地使用它。他们可能会这样称呼它:

dividend.setDate(myDate);
newDividend = dividend.setDate(myDate);
然后你会惊讶于为什么
股息的日期没有改变。他们应该这样使用它:

dividend.setDate(myDate);
newDividend = dividend.setDate(myDate);
为了使API更直观,最好将
setDate
方法重命名为类似
copyWith

newDividend = dividend.copyWith(myDate);
或者,如果您有许多字段,并且重载会造成混乱,您可以将它们称为
copyWithDate
copyWithComment


其他名称也是可能的,如其他答案中所述:
derivithdate
(和
derivithdate
),或者干脆
withDate
,您应该像字符串类一样实现您的类,它上面没有设置器。我们可以理解,如果没有人可以对它设置任何内容,那么它是不可变的。(可能您想将setter设置为私有的,或者您可能只想直接从股息类内部设置变量)

Font
,例如,有(a)
derivate
方法,可以创建从当前实例派生的新字体实例。

此函数只是构造函数的包装。重载构造函数以接受要复制的完整对象。否则,您可以将此函数重命名为getDistribution(它肯定不是setter)。

我看到的许多Java库都开始使用
作为“此对象的副本,但有以下更改”的前缀

例如:

public Dividend withDate() {
   ....
这有助于

Dividend newDividend = oldDividend.withDate(...).withAmount(...).withComment(...);

例如,遵循此模式(以及使用
plusXxx()
minusXxx()
作为“调整器”对象,例如采用增量而非绝对值)。

由于正在返回
红利
,用户可能会知道这是一个新的
红利
实例。即使这样,您也可以重新考虑名称。

Divident
是否有修改对象的
setComment
方法?那么它不是不可变的。如果您的setComment方法是private,那么只有这个类是不可变的。您可以尝试类似于
onDate
/
withDate
/
forDate
,,在这个例子中,我删除了setComment以避免混淆。同意-我觉得派生命名非常直观。如果我不知道它是不可变的,我会假设它是一个流畅的界面,并返回
this