iT邦幫忙

2

物件導向程式設計 : 里氏替換原則(LSP)

里氏替換原則(Liskov Substitution principle)

網路上有很多文章與範例在解釋6大原則,
但是還是很難只看一篇就能了解。
一言以蔽之 : 子類別必須可以替換父類別的功能
雖然是很簡單的觀念,但是理解起來還是很抽象。
今天就來統整一下這個原則吧

what is LSP?

以下截自wiki

里氏替換原則(Liskov Substitution principle)是對子類型的特別定義。
它由芭芭拉·里斯科夫(Barbara Liskov)在1987年在一次會議上名為「數據的抽象與層次」的演說中首先提出。
里氏替換原則的內容可以描述為: 「派生類(子類)對象可以在程式中代替其基類(超類)對象。」

在設計繼承時,需符合子類別必須可以替換父類別的功能

C# 之中有 IEnumerable > ICollection > IList > List
當interface實作時,需這樣宣告

IList<int> myList = new List<int>();  //這就是里氏替換原則

為什麼有這個原則呢?

我們在開發程式時,大部分的邏輯都是基於現實生活的,但是在撰寫過程中常常因考慮不周全,導致執行結果正確,但卻不符合現實情況,以下用常用的鳥類分類來解釋:
所有的鳥類都繼承"鳥"這個class
https://ithelp.ithome.com.tw/upload/images/20190605/2011769502nHuqoxlZ.png

public class bird
{
    public void eat(...)
    public void fly(...)
    public void Location(...)
    ...
}

所有鳥類都繼承bird這個class這沒有問題,但是有少數鳥類不會飛啊!!
如果讓chicken直接繼承,在程式方面雖然沒錯,但結果不是我們想要的,也不符合實際情況。

public class chicken:bird
{
    public void eat(...)
    public void fly(...)    //chicken不會飛啊
    public void Location(...)
    ...
}

此種問題是因父類別的設計有問題造成的
我們可以藉由增加繼承的層次來解決這個問題
在bird class 下多一層飛行的分類
https://ithelp.ithome.com.tw/upload/images/20190610/20117695pQdAZWHDPk.png

public class flying:bird  //會飛的
{
    public void fly(...)
    ...
}
public class flightless:bird  //不會飛的
{
    ...
}
public class chicken:flyless  //繼承不會飛
{
    public void eat(...)
    public void Location(...)
    ...
}

如此分開繼承後,上層類別就可透過下層類別來實作,也不改變其行為
這樣既不違背邏輯又可符合開閉原則

結論

里氏替換原則所規範的繼承,子類別必須擁有父類別的全部屬性和方法,避免子類別覆寫父類別的功能(更改傳回結果)

遵守里氏替換原則,可以建立良好的繼承,降低繼承造成的強耦合。


尚未有邦友留言

立即登入留言