1. 程式人生 > 其它 >里氏替換原則

里氏替換原則

技術標籤:里氏替換原則設計模式

OO 中的繼承性的思考和說明

  1. 繼承包含這樣一層含義:父類中凡是已經實現好的方法,實際上是在設定規範和契約,雖然它不強制要求所有的子類必須遵循這些契約,但是如果子類對這些已經實現的方法任意修改,就會對整個繼承體系造成破壞。
  2. 繼承在給程式設計帶來便利的同時,也帶來了弊端。比如使用繼承會給程式帶來侵入性,程式的可移植性降低, 增加物件間的耦合性,如果一個類被其他的類所繼承,則當這個類需要修改時,必須考慮到所有的子類,並且父類修改後,所有涉及到子類的功能都有可能產生故障
  3. 問題提出:在程式設計中,如何正確的使用繼承? => 里氏替換原則

基本介紹

  1. 里氏替換原則(Liskov Substitution Principle)在 1988 年,由麻省理工學院的以為姓裡的女士提出的。
  2. 如果對每個型別為 T1 的物件 o1,都有型別為 T2 的物件 o2,使得以 T1 定義的所有程式 P 在所有的物件 o1 都代換成 o2 時,程式 P 的行為沒有發生變化,那麼型別 T2 是型別 T1 的子型別。換句話說,所有引用基類的地方必須能透明地使用其子類的物件。(這點沒看懂)
  3. 在使用繼承時,遵循里氏替換原則,在子類中儘量不要重寫父類的方法
  4. 里氏替換原則告訴我們,繼承實際上讓兩個類耦合性增強了,在適當的情況下,可以通過聚合,組合,依賴 來解決問題

一個程式引發的問題和思考

public class Calculation {

    public Double function(Double d1,Double d2){
        return  d1 +d2;
    }
}

public class Mathematical extends Calculation {

    @Override
    public Double function(Double d1, Double d2) {
        return d1 - d2;
    }

    public Double function1(Double d1, Double d2){
        return function(d1,d2) + 9;
    }
}


public class Test {

    public static void main(String[] args) {
        Mathematical mathematical = new Mathematical();
        Double d = mathematical.function(8.0,9.5);
        System.out.println(d);
        Double d1 = mathematical.function1(8.0,9.5);
        System.out.println(d1);
    }
}
  1. 當父類有一個方法時,子類實現了父類的方法。而子類有業務變動時,父類的方法滿足不了需求,子類重寫了父類的方法,而且改變了裡面的業務 。造成的原有的功能出錯。這樣寫起來雖然簡單,但是整個體系的利用性會比較差,特別是執行多型比較頻繁的時候。
  2. 通用的做法是:原來的父類和子類都繼承一個理通俗的基類,原有的繼承關係去掉,採用依賴,聚合,組合等關係代替。
  3. 改進方案

public class Base {
    // 實現更基礎的方法
}

public class A extends Base {

    public int sub(int a,int b){
        return a-b;
    }
}


public class B extends Base {

    public A a = new A();

    public int add(int a,int b){
        return  a + b;
    }

    // 還是可以用A類的方法
    public int function(int a,int b){
        return this.a.sub(a,b);
    }
}