2018年9月29日 星期六

違反 LSP Liskov Substitution Principle 里氏替換原則

違反 LSP Liskov Substitution Principle 里氏替換原則

有很多人對於 LSP Liskov Substitution Principle 里氏替換原則 所講述的內容,看得很模糊,有些時候是學習者對於物件導向程式設計觀念不慎清楚、開發經歷中,也甚少經常設計類別繼承的程式碼,不過,也有人說,我都有設計類別繼承,要是我,才不會有這樣的問題;可是,這是個原則,講的是當您遵從這個原則之後,就不會設計出有行為異常的子類別,有些時候,您也可能需要維護別人開發的舊專案,這個專案也許不知道經過幾個人來維護過了,往往有需求變更的時候,為了客戶時效要求,手頭上有很多專案要開發,就直接繼承類別,產生新的子類別來設計出滿足變更需求的程式,當然,經過一段時間之後,這個專案上就會產生違反 LSP 的問題;不過,說實在的,若這個專案從頭到尾都是您自己開發,也是有可能產生違反 LSP 的問題。一旦程式碼出現違反 LSP 的原則,就會產生出許多意想不到的問題,而這些問題,很多時候是在設計與除錯時候,無法立即發現到的 (更多關於 LSP 的介紹,網路上已經有海量的文章,請各位自行去搜尋、研究)
現在,讓我們來看看底下的範例,您能夠看出它存在著甚麼問題嗎?
另外,他是否有遵從 LSP 原則嗎?
不論答案是肯定或者是否定,請您要提出的論述觀點,這樣,才能夠知道,您是否真正明瞭甚麼是 LSP Liskov Substitution Principle 里氏替換原則
class 鳥
{
    public virtual void 飛() { Console.WriteLine("鳥在飛"); }
    public virtual void 吃() { Console.WriteLine("鳥在吃"); }
}
class 老鷹 : 鳥
{
    public override void 飛() { Console.WriteLine("老鷹在飛"); }
    public override void 吃() { Console.WriteLine("老鷹在吃"); }
}
class 鴕鳥 : 鳥
{
    public override void 飛() { throw new NotSupportedException("鴕鳥不能飛"); }
    public override void 吃() { Console.WriteLine("老鷹在吃"); }
}
底下是使用上面類別的範例程式碼
class Program
{
    static void Main(string[] args)
    {
        List<鳥> birds = new List<鳥>();
        birds.Add(new 鳥());
        birds.Add(new 老鷹());
        birds.Add(new 鴕鳥());
        BirdsFly(birds);
    }
    static void BirdsFly(List<鳥> birdList)
    {
        foreach (var item in birdList)
        {
            item.飛();
        }
    }
}

沒有留言:

張貼留言