一些面向對象的設計法則(4)

法則4:Liskov替換法則(LSP)

使用指向基類(超類)的引用的函數,必須能夠在不知道具體派生類(子類)對象類型的情況下使用它們。

[ Function Thar Use Referennces To Base(Super) Classes Must Be Able To Use Objects
Of Derived(Sub) Classes Without Knowing It ]




  • Liskov替換法則





    1.顯而易見,Liskov替換法則(LSP)是根據我所熟知的"多態"而得出的。

    2.例如:



    方法drawShape應該可與Sharp超類的任何子類一起工作(或者,若Sharp爲Java接口,則該方法可與任何實現了Sharp接口的類一起工作)

    但是當我們在實現子類時必須要謹慎對待,以確保我們不會無意中違背了LSP。





    3.若一個函數未能滿足LSP,那麼可能是因爲它顯式地引用了超類的一些或所有子類。這樣的函數也違背了OCP,因爲當我們創建一個新的子類時,會不得不進行代碼的修改。




  • LSP示例



    1. 考慮下面Rectangle類:



    2.現在,Square類會如何呢?顯然,一個正方形是一個四邊形,因此Square類應該從Rectangle類派生而來,對否?讓我們看一看!

    3.觀察可得:

    a.正方形不需要將高和寬都作爲屬性,但是總之它將繼承自Rectangle。因此,每一個Square對象會浪費一點內存,但這並不是一個主要問題。

    b.繼承而來的setWidth()和setHeight()方法對於Square而言並非真正地適合,因爲一個正方形的高和寬是相同。因此我們將需要重寫setWidth()和setHeight()方法。不得不重寫這些簡單的方法有可能是一種不恰當的繼承使用方式。


    3.Square類如下:










4. 看起來都還不錯。但是讓我們檢驗一下!








5. 測試程序輸出:







6.看上去好像我們違背了LSP!


7.這裏的問題出在哪裏呢?編寫testLsp()方法的程序員做了一個合理的假設,即改變Rectangle的寬而保持它的高不變。

8.在將一個Square對象傳遞給這樣一個方法時產生了問題,顯然是違背了LSP

9.Square和Rectangle類是相互一致和合法的。儘管程序員對基類作了合理的假設,但其所編寫的方法仍然會導致設計模型的失敗。

10.不能孤立地去看待解決方案,必須根據設計用戶所做的合理假設來看待它們。


11. 一個數學意義上的正方形可能是一個四邊形,但是一個Square對象不是一個Rectangle對象,因爲一個Square對象的行爲與一個Rectangle對象的行爲是不一致的!

12.從行爲上來說,一個Square不是一個Rectangle!一個Square對象與一個Rectangle對象之間不具有多態的特徵。






  • 總結





    1.Liskov替換法則(LSP)清楚地表明瞭ISA關係全部都是與行爲有關的。

    2.爲了保持LSP(並與開放-封閉法則一起),所有子類必須符合使用基類的client所期望的行爲。

    3.一個子類型不得具有比基類型(base type)更多的限制,可能這對於基類型來說是合法的,但是可能會因爲違背子類型的其中一個額外限制,從而違背了LSP!

    4.LSP保證一個子類總是能夠被用在其基類可以出現的地方!

     
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章