C# 設計原則-里氏替換原則
阿新 • • 發佈:2020-12-29
里氏替換原則,全稱Liskov Substitution Principle,英文縮寫LSP。
一個程式中如果使用的是一個父類,那麼該程式一定適用於其子類,而且程式察覺不出父類和子類物件的區別。也就是說在程式中,把父類替換成它的子類,程式的行為沒有任何變化。
關於里氏替換原則的反例有不少,舉個例子,企鵝不會飛。
Birds鳥類、Sparrow麻雀類,所有的鳥類都有飛行速度。
public abstract class Birds { //所有鳥類都應該具有飛行速度 public abstract double FlySpeed(); } public classSparrow : Birds { public override double FlySpeed() { return 12; } }
此時新增一個Penguin企鵝類,因為企鵝也是鳥類,所以繼承Birds鳥類。
public class Penguin : Birds { public override double FlySpeed() { return 0; } }
但因為企鵝不會飛,所以飛行速度設為0,這也算是實現了FlySpeed的方法,執行結果也沒問題。但如果現在有一個方法Fly用來計算一隻鳥飛行300米所需要的時間。
public static double Fly(Birds bird) { return 300 / bird.FlySpeed(); }
當把企鵝Penguin放進去,會出現報錯,因為300/0是不合理的,這就不滿足里氏替換原則。不滿足該原則的原因還是因為Penguin企鵝類沒有完全繼承Birds鳥類,因為企鵝不能飛,實現不了FlySpeed方法。所以要解決這個問題有兩種方案。
第一種是直接在Fly方法中進行判斷。
public static double Fly(Birds bird) { //如果傳入的型別為企鵝,預設返回0 if (bird.GetType().Equals(typeof(Penguin))) { return 0; } else { return 300 / bird.FlySpeed(); } }
可這樣就會違反開閉原則,以後如果需要新增新功能,得不斷修改。
第二種就是Penguin企鵝類不要繼承Birds鳥類,實際上,這裡Penguin企鵝就是強行繼承Birds鳥類,雖然現實中企鵝也是鳥,但在程式碼中卻不行。
總結一下里氏替換原則的特點,就是子類可以拓展父類的功能,但是不能改變父類原有的功能。子類可以重寫父類的抽象方法,但不能覆蓋父類的非抽象方法。子類可以增加自己獨有的方法。