章節概述#
上一章結尾冒出了一個令人不安的問題:如果拿 Franc 和 Dollar 比較,會發生什麼事? 本章要面對這個問題,確保不同貨幣之間的等值比較是正確的。
問題浮現:Franc 等於 Dollar?#
將這個擔憂轉化為測試:
public void testEquality() {
assertTrue(new Dollar(5).equals(new Dollar(5)));
assertFalse(new Dollar(5).equals(new Dollar(6)));
assertTrue(new Franc(5).equals(new Franc(5)));
assertFalse(new Franc(5).equals(new Franc(6)));
assertFalse(new Franc(5).equals(new Dollar(5)));
}最後一行是新增的——5 Franc 不應該等於 5 Dollar。但測試失敗了:目前的 equals() 只比較金額,沒有區分貨幣類型,因此 Dollar 和 Franc 被視為相等。
用 getClass() 修正#
修正方式是在 equals() 中加入類別檢查——兩個 Money 物件只有在金額和類別都相同時才相等:
public boolean equals(Object object) {
Money money = (Money) object;
return amount == money.amount
&& getClass().equals(money.getClass());
}測試通過了。
補充: 作者承認在模型程式碼中使用
getClass()有點「壞味道(code smell)」。理想上應該用業務領域中有意義的概念(如貨幣 currency)來區分,而不是 Java 物件的類別。但目前尚未引入 currency 的概念,而且僅為此引入似乎理由不夠充分,所以暫時這樣處理。
更新後的待辦清單#
清單上劃掉了「Compare Francs with Dollars」,同時新增了一個疑問:
Compare Francs to Dollars- Currency?(新增)
接下來需要消除 times() 的重複,才能進入混合貨幣運算。
本章小結#
- 將一個令人困擾的疑慮轉化為測試
- 用合理但不完美的方式(
getClass())讓測試通過 - 決定不過早引入更多設計,直到有更好的動機