你有沒有遇到過這種情況:當你在開發過程中,使用了子類別替換父類別,結果卻發現程式變得不正常了?這很可能是你違反了「里氏替換原則 (Liskov Substitution Principle, LSP)」。LSP 是物件導向設計中的一個重要原則,能確保我們使用繼承時不會破壞程式的穩定性。
什麼是里氏替換原則?
里氏替換原則它強調:「子類別應該可以無縫替換父類別,而不會影響程式的正確性」。換句話說,在程式中某個地方用的是父類別,未來改成子類別後,程式還能正常運作。
這裡的核心思想是:繼承不只是重用父類別的程式碼,而是要確保子類別能「完美替代」父類別。如果某個子類別改變了父類別的行為邏輯,可能會破壞程式的穩定性。
舉個簡單的例子
想像有一個基礎類別叫做「鳥」,裡面有一個方法是「飛行」。如果我們繼承了一個新的類別叫「企鵝」,因為企鵝不能飛,這時候問題就來了。如果我們強制企鵝也有「飛行」這個行為,那麼當程式要求企鵝飛時,程式就會崩潰或出錯,因為它實際上無法做到。
正確設計的應該怎麼做?
所以在這個例子中,我們應該避免讓企鵝繼承那個飛行行為,那麼正確的做法是,我們可以把「飛行」行為拆分到另一個更適合的類別,而不強制所有鳥類都必須會飛。讓只有會飛的鳥類才有「飛行」這個行為,這樣一來,會飛的鳥類和不會飛的鳥類就不會再混淆,這樣的設計不僅清晰也變得更合理,還能避免潛在的錯誤,也符合里氏替換原則。
正確的設計應該是讓不同的類別各自處理自己的行為,而不是強行讓不相關的子類別擁有父類別的所有特徵。這樣可以確保子類別能夠替代父類別,而不會破壞系統的穩定性。
為什麼要遵守 LSP?
遵守 LSP 有助於程式的穩定性和可預測性。當子類別能無縫替代父類別時,系統就能更容易地進行維護與擴展。相反地,違反 LSP 的設計則容易引發隱藏的錯誤,這些錯誤往往難以發現跟修正。
總結一下,里氏替換原則是一種設計上的「最佳實踐」,幫助開發者更好地處理繼承關係,它還代表著更好的程式設計習慣和更健全的系統架構。
有興趣深入體會設計原則的朋友,可以參考我今年在iThome鐵人賽的文章。
https://ithelp.ithome.com.tw/articles/10355395