Java中多態是否違背了里氏替換原則


問題產生原因:

​ 里氏替換原則:子類對象能夠替換父類對象,而程序邏輯不變,要求子類避免重寫父類方法。

​ 多態存在條件之一:要求子類重寫父類的方法。

問題解釋:

LSP 的原定義比較復雜,一般對里氏替換原則 LSP 的解釋為:子類對象能夠替換父類對象,而程序邏輯不變。

這一原則是針對繼承而言的,所以本質上是普遍性與特殊性的關系:普遍性孕育於所有的特殊性中,特殊性違背不了普遍性。普遍性一旦被特殊化就不再是普遍性,這勢必影響所有的特殊性。所以,就程序設計而言,子類不可修改父類。

里氏代換原則就是上述規律的結論:程序中對普遍性的依賴,可以由特殊性滿足,因為特殊性中蘊含着普遍性。也就是:子類能夠替換父類,而程序邏輯不變。

里氏轉換原則要求子類從抽象繼承而不是從具體繼承,如果從抽象繼承,子類必然要重寫父類方法。因此里氏轉換原則和多態是相輔相成的。

而要滿足里氏代換原則,本質上就是要讓代碼設計符合上述規律:特殊性不可違背普遍性,也就是子類不可修改父類。所以,實現繼承時,父級應當是抽象類或者接口,而不能是可實例化的類。

里氏替換原則,就是讓你的某一段程序耦合於基類或者接口,而不是具體繼承了基類的子類或實現接口的具體類型。僅替換子類不會讓你這個程序的屬性有所改變。

通俗講就是,我聲明的一個類或接口,然后隨意的 new 繼承這個基類的子類或者實現這個接口的類。然后我隨意的調用這個基類或接口的方法,程序都正確執行不出現問題。

里氏替換原則有至少以下兩種含義:

  1. 里氏替換原則是針對繼承而言的,如果繼承是為了實現代碼重用,也就是為了共享方法,那么共享的父類方法就應該保持不變,不能被子類重新定義。子類只能通過新添加方法來擴展功能,父類和子類都可以實例化,而子類繼承的方法和父類是一樣的,父類調用方法的地方,子類也可以調用同一個繼承得來的,邏輯和父類一致的方法,這時用子類對象將父類對象替換掉時,當然邏輯一致,相安無事。

  2. 如果繼承的目的是為了多態,而多態的前提就是子類覆蓋並重新定義父類的方法,為了符合 LSP,我們應該將父類定義為抽象類,並定義抽象方法,讓子類重新定義這些方法,當父類是抽象類時,父類就是不能實例化,所以也不存在可實例化的父類對象在程序里。也就不存在子類替換父類實例(根本不存在父類實例了)時邏輯不一致的可能。

不符合 LSP 的最常見的情況是,父類和子類都是可實例化的非抽象類,且父類的方法被子類重新定義,這一類的實現繼承會造成父類和子類間的強耦合,也就是實際上並不相關的屬性和方法牽強附會在一起,不利於程序擴展和維護。

符合 LSP 的方法:盡量不要從可實例化的父類中繼承,而是要使用基於抽象類和接口的繼承。

多態與里氏替換原則是否沖突?

里氏替換原則要求特殊性不可違背普遍性,這個違背是指子類修改父類。而多態是指子類本身就父類中的普遍性進行特殊化的繼承,實際上並未修改父類。所以,兩者不沖突,是一種補充關系。多態使得父類的普遍性能夠在子類中進行特殊化繼承。里氏代換原則要求繼承關系必須符合普遍性與特殊性的規律。

參考:

https://www.zhihu.com/question/27191817


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM