繼承是 OO 核心,Java 分介面繼承與實作繼承。濫用實作繼承帶來強耦合、脆弱基底類別、邏輯洩漏等問題。本文以 Stack 繼承 ArrayList 為例,剖析弊端並探討替代方案。
實作繼承的三大痛點
- 過度暴露:Stack 繼承 ArrayList 導致所有 public 方法外洩,甚至包含破壞堆疊不變性的方法。
- 脆弱基底類別:基底類別新增方法可能邏輯破壞衍生類,修改基底須檢查所有衍生類,跨團隊維護極易埋下 Bug。
- 不安全的「不支援」模式:基底類別拋出異常或宣告抽象方法強迫衍生類實作,僅能在執行期發現,極不安全。
設計原則:IS-A vs Has-A
- IS-A 關係才考慮繼承,但非絕對理由。
- Has-A 關係優先採用委派/組合,封裝實作細節,降低耦合。
- GOF 設計模式多數目的即在消除不當繼承。
介面導向程式設計:面向抽象而非具體
- 方法參數、欄位宣告為介面型別(如
Collection 而非 ArrayList),利用多型實現易擴展、穩定架構。
- 核心價值:隱藏實作,對分層架構與框架設計至關重要。
- 物件建立交由工廠、抽象工廠、依賴注入(IoC)等建立型模式處理。
總結
繼承與介面皆非銀彈,濫用皆害。DAO/Service 一介面一實作雖為業界慣例,專案實況仍需權衡。「瘦」不一定「好」,最佳實踐源自經驗累積與批判性思考。