「整體大於部分之和」——隨著方法增加,程式控制流程爆炸式增長,大型系統極易失控。重載/覆寫方法雖強大,卻引入 Broken Dispatch(調度失效) 錯誤模式。
foo 的參數,被傳給支援更寬鬆參數類型的方法 goo。goo 透過這些參數呼叫 foo。goo 內參數靜態類型更寬泛,導致調用了錯誤版本的 foo。此錯誤極難診斷:僅新增方法(未修改既有代碼)即可引入錯誤,且程式可能長時間正常運行才暴露問題。
以不可變列表實現為例:LinkedList 構造子接受 String 參數,委託 Cons 建構。若後續在 Cons 新增單一 String 參數的構造子(解析字串表示法),LinkedList 原構造子調用將被重導向此新構造子:
// LinkedList 原構造子
public LinkedList(String _first) { this.value = new Cons(_first); }
// Cons 新增構造子(稍後加入)
Cons(String representation) { /* 解析字串 */ }
若傳入非法字串導致解析崩潰;更隱蔽的是:若字串恰巧合法,程式帶著錯誤資料繼續運行——破壞者資料 悄然植入。
new Cons((Object)_first)。但需在所有調用點處理,對客戶代碼不友善。Cons.fromString(String) 回傳 Cons,避免重載衝突,兼顧便利與安全。重載/覆寫方法時,參數結構是確保按意圖調度的關鍵。優先編寫完整單元測試,新增重載後立即回歸測試。
下回將探討尾遞歸對 Java 效能的影響,隨後回歸錯誤模式系列。