定義:全部引用基類的地方必須能透明地使用其子類的對象。
問題:有一功能P1,由類A來完成。如今須要將功能P1進行擴展,擴展後的功能爲P(P由原有功能P1和新功能P2組成)。
功能P由類A的子類B來完成,子類B在完成新功能P2的同時有可能會致使原有功能P1發生故障。
解決:當使用繼承時,遵循里氏替換原則。類B繼承類A時,除添加新的方法完成新增功能P2外,儘可能不要重寫父類A的方法,
也儘可能不要重載父類A的方法。
舉個栗子:士兵使用武器進行射擊,包括武器的類別和特色的介紹。
狀況一:士兵使用手槍進行射擊,實現結果爲:手槍小,便於攜帶;手槍一次只能發射一顆子彈;手槍開始射擊。
1. 新建一個手槍類HandGun,介紹手槍的特色,代碼以下:
2. 新建一個士兵類Soldier,包含手槍的相關方法,代碼以下:
3. 在類LSPFragment中實現士兵用手槍進行射擊,代碼以下:
4. 運行後的結果爲:
如今咱們須要實現士兵使用步槍進行射擊,因而咱們就要新增步槍類RifleGun,而且要去修改士兵類Soldier。
狀況二:士兵使用步槍進行射擊,實現結果爲:步槍長,不益於攜帶;步槍能夠連續射擊;步槍開始射擊。
1.新建一個步槍類RifleGun,介紹步槍的特色,代碼以下:
2. 修改士兵類Soldier,包含手槍和步槍的相關方法,代碼以下:
3. 修改類LSPFragment,分別實現士兵用手槍和步槍進行射擊,代碼以下:
4. 運行後的結果爲:
以上的實現方式能夠看出,一旦新增功能(武器),就會去修改類Soldier和類LSPFragment,這樣不只會影響到原有的功能,
擴展起來也十分不方便,假設邏輯比較複雜的話,就須要去修改或重構大量的代碼。
因而就要使用里氏替換原則來解決這個問題,新增一個類BaseGun,包含武器的特色和射擊動做的方法,讓手槍類HandGun和
步槍類RifleGun都繼承於它,分別來實現,代碼以下:
1. 新增類BaseGun,包含武器的特色和射擊動做的方法,代碼以下:
2. 讓手槍類HandGun和步槍類RifleGun都繼承於它,分別來實現以上兩個方法,代碼以下:
3. 修改士兵類Soldier,讓它依賴類BaseGun,代碼以下:
4. 修改類LSPFragment,實現士兵用手槍和步槍進行射擊,代碼以下:
5. 運行後的結果同上。
以上實現方式能夠看出,子類(手槍類HandGun和步槍類RifleGun)繼承父類BaseGun,並徹底實現父類BaseGun中的抽象方法來實現功能。
其中,士兵類Soldier依賴於抽象類BaseGun來調用相應的方法,在類LSPFragment中能夠看出,父類均可以用子類來代替,但不能改變父類
原有的功能,在子類中能夠任意擴展功能,這就是所謂的「全部引用基類的地方必須能透明地使用其子類的對象。」
下面,咱們再新增一個武器類(機槍類CachineGun),並在各個子類中分別擴展功能,好比增長武器名。代碼以下:
狀況三:
1. 士兵使用手槍進行射擊,實現結果爲:士兵使用的武器是手槍;手槍小,便於攜帶;手槍一次只能發射一顆子彈;手槍開始射擊。
2. 士兵使用步槍進行射擊,實現結果爲:士兵使用的武器是步槍;步槍長,不益於攜帶;步槍能夠連續射擊;步槍開始射擊。
3. 士兵使用機槍進行射擊,實現結果爲:士兵使用的武器是機槍;機槍長,火力十分兇猛;機槍能夠掃射;機槍開始射擊。
代碼以下所示:
1. 新建一個機槍類CachineGun,介紹機槍的特色,增長機槍獨有的方法,代碼以下:
2. 修改手槍類HandGun和步槍類RifleGun,分別增長各自獨有的方法,代碼以下:
3. 此時不須要修改類Solider,只須要在類LSPFragment中增長調用方法,便可實現士兵用手槍、步槍和機槍進行射擊,代碼以下:
4. 運行後的結果爲:
以上,使用繼承抽象類來擴展功能,並遵循里氏替換原則,實現起來是否是很方便呀!
原則:子類能夠擴展父類的功能,但不能改變父類原有的功能。 父類能出現的地方均可以用子類來代替,並且換成子類也不會出現任何錯誤或異常,而使用者也無需知道是父類仍是子類, 但反過來則不成立。總之,就是抽象。 1. 子類必須徹底實現父類的抽象方法,但不能覆蓋父類的非抽象方法; 2. 子類中能夠增長本身特有的方法; 3. 當子類的方法重載父類的方法時,方法的前置條件(即方法的形參)要比父類方法的輸入參數要更寬鬆; 4.當子類的方法實現父類的抽象方法時,方法的後置條件(即方法的返回值)要比父類更嚴格。優勢: 1. 提升代碼的重用性,子類擁有父類的方法和屬性; 2. 提升代碼的可擴展性,子類可形似於父類,但異於父類,保留自個人特性;缺點: 1. 繼承是侵入性的,只要繼承就必須擁有父類的全部方法和屬性,在必定程度上約束了子類,下降了代碼的靈活性; 2. 增長了耦合,當父類的常量、變量或者方法被修改了,須要考慮子類的修改,因此一旦父類有了變更,極可能會形成 很是糟糕的結果,要重構大量的代碼。