以下內容僅為個人筆記使用,原始文章連結:
https://www.jyt0532.com/2020/03/22/lsp/
Liskov Substitution Principle
Prerequisite:
- subType vs subClass
- Subclasses allow one to reuse the code inside classes – both instance variable declarations and method definitions. Thus they are useful in supporting code reuse inside a class. Subtyping on the other hand is useful in supporting reuse externally, giving rise to a form of polymorphism. That is, once a data type is determined to be a subtype of another, any function or procedure that could be applied to elements of the supertype can also be applied to elements of the subtype.
- Subtype = Subclass(realization) which can be substituted for the type it extends(implements)
- Invariant: 指的是無論何時何地 你單看一個類別的instance 都應該要遵守的 就叫做invariant
- Constraint: 指的是對於某一個物件來說 在歷史上的兩個不同時間 應該要遵循什麼事情
- 為什麼需要Liskov substitution principle:
以正方形、長方形為例子:
那如果我違反了會怎麼樣呢 Square 不是 Rectangle 的 SubType 世界會塌嗎?
世界不會塌 但是這不是個好架構 想像一下你是個使用Rectangle跟Square類別的人 當你拿到一個Rectangle的時候
1.因為你不確定當初設計Rectangle的人 有沒有保證每個繼承Rectangle的類別都是Rectangle的subType
2.你知道如果一個Rectangle的subClass不是Rectangle的subType的話,你預期會應該會正確的行為有可能會不正確(比如testRectangle函數) - 何謂Covariance: https://byjus.com/maths/covariance/
何為Subtype的7個規則:
規則一: Covariance of argument // p.s. superClass和subType的input argument要ㄧ致(p.s. 數量和type)
規則二: Covariance of result // p.s. superClass和subType的回傳值要一致(p.s. 數量和type)
規則三: Exception rule // p.s. 當你實作或是繼承一個superClass的方法時 拋出的例外 必須是superClass方法拋出的例外的subType
規則四: Pre-condition rule // p.s. subType的函式需要的precondition 不能比baseType的還要嚴謹(strict)
// 你也可以想成 在所有可以執行baseType.methodA的地方 你都應該可以執行subType.methodA
規則五: Post-condition rule // p.s. subType的函式需要的postcondition 不能比baseType的還要鬆散(weak)
規則六: Invariant rule // p.s. 一個subtype的類別的invariant 必須包含所有baseType的invariant
規則七: Constraint rule // p.s. 一個subtype的類別的constraint 必須包含所有baseType的constraint
用上述7個規則來檢查正方形是不是長方形的subType:
1.Covariance of argument: 函式argument一樣 遵守
2.Covariance of result: 函式都回傳void 遵守
3.Exception rule: 都沒有拋出例外 遵守
4.Pre-condition rule: 都沒有Pre-condition 遵守
5.Post-condition rule: 都沒有Post-condition 遵守
6.Invariant rule: 長方形沒有Invariant 正方形的Invariant就是長寬一樣 但在我們正方形的實作中我們有遵守這個Invariant(所以如果我們setWidth只改width 那這條就沒遵守了) 所以這條有遵守
7.Constraint rule: 有趣了 這條沒遵守 因為在Rectangle的Contraint包含了
i. setWidth時不可以動到height
ii. setHeight時不可以動到width
=> 正方形違反constraint rule,所以正方形不是長方形的subType