软件构造学习笔记-第八周
本周重點是Liskov可替換原則。它要求父類和子類的行為一致性,子類要有更強的不變量、更弱的前置條件、更強的后置條件。在該原則的要求下,每個子類都可以對父類進行替換。這在開發過程中會帶來極大的便利,在實驗3中學習并運用該原則。
有關復用
1.復用的級別
-源代碼級別的復用
-模塊級別的復用(類/抽象類/接口)
-庫級別的復用(API/包)
-系統級別的復用(框架)
2.軟件構造過程中任何實體都可能被復用。比如需求、規約、數據、測試用例、文檔等。
3.白盒復用對應繼承,黑盒復用對應委托(顯示委托:明確指出調用某個對象的功能;隱式委托:不明確指出調用某個對象的功能,例如敲擊鍵盤)
子類型多態
客戶端可用統一的方式處理不同類型的對象
協變和反協變
1.協變:子類型方法的返回值不變或者更加具體(原返回值的子類)、子類型拋出的異常不變或者更加具體(原異常類型的子類)
2.反協變:子類型方法的參數值不變或者更加抽象(原類型的父類),或者不拋出
但是對Java而言不支持,因為被視為overload
3.數組是協變的。Java不支持泛型數組,因為運行時存在泛型擦除。
Liskov可替換原則
(要求父類和子類的行為一致性)
-更強的不變量
-更弱的前置條件
-更強的后置條件
Java編譯器有關繼承的規則
-子類型可以增加方法,但是不能刪除方法
-子類型需要實現抽象類型中的所有未實現方法
-子類型中重寫的方法的 返回值 必須 相同/子類型/符合協變
-子類型中重寫的方法的 參數 必須 相同/符合協變
-子類型中重寫的方法不能拋出額外異常
A是父類,B是子類,A中有方法someMethod(Integer n),B中有方法someMethod(Number n)。如果A a = new B(),并且向someMethod傳入Integer、Number,則分別調用哪個類的方法?
答:傳入Integer類型調用A的方法,傳入Number類型報錯。
泛型中的LSP
1.ArrayList是List的子類型
List不是List的子類型
如果兩個泛型存在父子類型關系,則泛型的類型必須相同。因為運行時存在泛型擦除。編譯階段報錯,因為運行時進行擦除后相同
2.通配符可以解決泛型擦除問題,比如List<?>(說明任何類型都可用),用于和泛型的具體類型無關的場合,或者類型使用了Object類的操作,即放入什么類型都不影響使用。
3.<? super A>表示可存A和A的父類,<? extends A>表示可存A和A的子類。
例如,List是List<?>的子類型,同樣是List<? extends Object>的子類型。List是List<? super String>的子類型。
委托和組合
1.建立委托之間的聯系。
2.相較于繼承,委托是比較細粒度的復用方式。一般來說,只需要用到一個類的部分而非全部方法時,使用委托。當一個對象需要“存在一個”或者“使用一個”,而不是“是一個”時使用委托。
3.不需要兩個類之間存在語義聯系。在實驗2中,FriendshipGraph和Graph存在明顯的父子類關系,可用繼承。也可用委托。
4.委托發生在對象層面,繼承發生在類的層面。
5.在計算獎金的例子中,核心問題是每個Employee對象的獎金計算方法都不同,在對象層面而非類層面。
6.動物例子。考慮動物的飛和叫。
將飛法設置一個接口,針對不同的飛法,實現該接口的多個類。叫法同理。然后將兩個接口整合到鴨子的接口(用extends),再實現鴨子的類。最后繼承該類實現種類細分。
具體實現(右下角的Duck最好修改為Ducklike,因為聲明變量最好用父類)
7.委托的分類
委托分為使用(臨時性)和關聯(永久性)。
以下例子是臨時性委托,只有執行方法時才產生關聯
以下是永久性委托,將使用的類內化成屬性,屬于對象的一部分。又分為組合(調用類無法改變,更強的關聯)和聚合(調用類可以改變,更弱的關聯)
上為聚合,下為組合
總結
以上是生活随笔為你收集整理的软件构造学习笔记-第八周的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 软件构造学习笔记-第七周
- 下一篇: 大枣茶的功效与作用、禁忌和食用方法