繼承階層越疊越深,什麼時候算太深?

Easy★★★★★Studied

FromRefactoring for Software Design Smells

Concepts practiced📏 組合優於繼承 (Composition over Inheritance)📏 簡單設計三原則 (DRY / KISS / YAGNI)

Convention: read the requirements & constraints first, sketch your own design, then expand the reference to compare.

📚 From the Books

繼承階層越疊越深,什麼時候算太深?ProblemEasy反模式辨識

一條繼承鏈一層疊一層,葉子類別繼承了祖先的一大堆方法與欄位,行為難以預測。這是 Deep Hierarchy(過深階層)。多深才算太深?怎麼收?

🎯 Scenario

// 每層只加一點點、卻越疊越高的 list-like 深階層
abstract class A
open class B : A()
open class C : B()
open class D : C()
open class E : D()
open class F : E()
class G : F()   // G 繼承了 A~F 全部成員,其中大半根本沒用到

壞味道:Deep Hierarchy。經驗法則:深度超過六層即可視為過深。書中案例 DatagramChannel 的介面繼承樹深達 7 層;SynthCheckBoxUI 是「深而 list-like」——每層只加少量方法、部分在中間層被覆寫,理解某個繼承方法的真實語意極其費力。

🧠 Intuition

TIP

先別看下面。沿著這條鏈往上數:超過六層了嗎? 再看每一層——它是因為「真有一群子型別共享這層行為」而存在,還是只是「為了重用 / 為想像中的未來」硬插進來的中介層?

⚖️ Reference Design

為什麼過深會痛
  • 葉子類別繼承大量方法 → 行為難預測。
  • 父方法在中間層被多次覆寫 → 葉子層的語意不明確。
  • 父欄位可能被子類別的局部變數遮蓋(shadow) → 難以追蹤。
  • 常與 Speculative Hierarchy 同時出現:為未來預留中介型別,深度自然被拉長(兩者本質不同,但常結伴)。
解法:collapse 掉多餘中介層
// collapse hierarchy:把只用來『標記型別』或推測性的中介層壓平
interface A            // 保留真正需要的抽象
class G : A            // 需要的行為用組合注入,而非靠六層繼承拿到
  • 套用 collapse hierarchy:移除多餘或推測性的中介抽象。
  • marker 型別可改用註解:只為 instanceof/is 檢查而存在的中介介面(如 InterruptibleChannel),可用 @annotation 取代,直接砍掉一層。
  • 需要重用祖先能力時,優先考慮組合優於繼承:把能力做成協作者注入,而不是靠加深階層繼承下來。
  • 呼應 YAGNI:別為想像中的重用預留中介層。
務實例外與真實代價
  • Deep Hierarchy 確實能促進重用——成熟框架/函式庫常有深階層,是重用 vs.(理解性、可變更性、可靠性、效能)之間的有意權衡
  • 但代價可能很實:書中軼事——某遠端監控應用為每種裝置建一個類別、階層越來越深,葉子物件繼承了祖先所有欄位(大半沒用),每個物件數百 KB、數千個並存 → 記憶體耗盡、效能崩潰。設計結構會直接砸到執行期品質。

🔑 Takeaways

✍️ My Notes

No notes yet — jot your takeaways or Q&A here.

📖 Further Reading