1. 程式人生 > 實用技巧 >C# 設計原則-里氏替換原則

C# 設計原則-里氏替換原則

  里氏替換原則,全稱Liskov Substitution Principle,英文縮寫LSP。

  一個程式中如果使用的是一個父類,那麼該程式一定適用於其子類,而且程式察覺不出父類和子類物件的區別。也就是說在程式中,把父類替換成它的子類,程式的行為沒有任何變化。

  關於里氏替換原則的反例有不少,舉個例子,企鵝不會飛。

  Birds鳥類、Sparrow麻雀類,所有的鳥類都有飛行速度。

public abstract class Birds
{
    //所有鳥類都應該具有飛行速度
    public abstract double FlySpeed();
}

public class
Sparrow : 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鳥類,雖然現實中企鵝也是鳥,但在程式碼中卻不行。

  總結一下里氏替換原則的特點,就是子類可以拓展父類的功能,但是不能改變父類原有的功能。子類可以重寫父類的抽象方法,但不能覆蓋父類的非抽象方法。子類可以增加自己獨有的方法。