2010-08-01 69 views
6

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之外還有更好的命名約定嗎?

+2

Class'Divident'有一個'setComment'方法來修改對象嗎?然後它不是不可變的。 – Jesper 2010-08-01 16:25:56

+0

如果你的setComment方法是私有的,那麼只有這個類是不可變的。 – Gopi 2010-08-01 16:29:41

+5

而不是'setDate',你可以嘗試像'onDate' /'withDate' /'forDate'等。 – polygenelubricants 2010-08-01 16:36:24

回答

10

如果你有setter,你的班級將看起來很可變,而用戶可能會以錯誤的方式使用它。他們可能會這樣稱呼它:

dividend.setDate(myDate); 

然後驚訝爲什麼dividend的日期並沒有改變。他們應該用這樣的:

newDividend = dividend.setDate(myDate); 

爲了使API更加直觀,倒不如重新命名setDate方法類似copyWith

newDividend = dividend.copyWith(myDate); 

或者,如果你有很多領域並且超載會令人困惑,您可以將它們稱爲copyWithDatecopyWithComment

也可以使用其他名稱,如其他答案中所述:derive(和deriveWithDate)或簡單地withDate

1

你應該實現你的類就像一個String類,它沒有setter。可以理解的是,如果沒有人能設置任何東西,它是不可改變的。 (也許你可能想讓setter變爲private,或者你可能只想直接從你的Dividend類中設置變量)

3

Font例如,有(a)derive創建新字體實例的方法從當前的一個。

+0

同意 - 我發現派生命名非常直觀。 – mikera 2010-08-01 19:03:34

-1

這個函數只是構造函數的一個包裝。重載構造函數以接受要複製的完整股息對象。否則,你可以重命名這個函數getDividend(它絕對不是一個setter)。

2

我見過的許多Java庫都開始使用with作爲'該對象的副本,以下更改的前綴'。

例如:

public Dividend withDate() { 
    .... 

其適合於

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

JSR-310,例如,遵循以下模式(以及使用plusXxx()minusXxx()爲此採取的Δ '調節' 對象例如,而不是絕對值)。

-1

由於Dividend正在返回,用戶可能會知道它是一個新的Dividend實例。即使那樣,你可能會重新考慮這個名字。

+0

我會假設它是一個流暢的接口,如果我不知道它是不可變的,就返回'this'。 – ILMTitan 2010-08-02 14:44:00