OO 中的繼承性的思考和說明
-
繼承包含這樣一層含義:父類中凡是已經實作好的方法,實際上是在設定規范和契約,雖然它不強制要求所有 的子類必須遵循這些契約,但是如果子類對這些已經實作的方法任意修改,就會對整個繼承體系造成破壞,
-
繼承在給程式設計帶來便利的同時,也帶來了弊端,比如使用繼承會給程式帶來侵入性,程式的可移植性降低, 增加物件間的耦合性,如果一個類被其他的類所繼承,則當這個類需要修改時,必須考慮到所有的子類,并且 父類修改后,所有涉及到子類的功能都有可能產生故障
-
問題提出:在編程中,如何正確的使用繼承? => 里氏替換原則
基本介紹
1.里氏替換原則(Liskov Substitution Principle)在 1988 年,由麻省理工學院的以為姓里的女士提出的,
-
如果對每個型別為 T1 的物件 o1,都有型別為 T2 的物件 o2,使得以 T1 定義的所有程式 P 在所有的物件 o1 都 代換成 o2 時,程式 P 的行為沒有發生變化,那么型別 T2 是型別 T1 的子型別,換句話說,所有參考基類的地 方必須能透明地使用其子類的物件,
3.在使用繼承時,遵循里氏替換原則,在子類中盡量不要重寫父類的方法
-
里氏替換原則告訴我們,繼承實際上讓兩個類耦合性增強了,在適當的情況下,可以通過聚合,組合,依賴 來 解決問題,
package com.atguigu.principle.liskov; public class Liskov { public static void main(String[] args) { // TODO Auto-generated method stub A a = new A(); System.out.println("11-3=" + a.func1(11, 3)); System.out.println("1-8=" + a.func1(1, 8)); System.out.println("-----------------------"); B b = new B(); System.out.println("11-3=" + b.func1(11, 3));//這里本意是求出11-3 System.out.println("1-8=" + b.func1(1, 8));// 1-8 System.out.println("11+3+9=" + b.func2(11, 3)); } } // A類 class A { // 回傳兩個數的差 public int func1(int num1, int num2) { return num1 - num2; } } // B類繼承了A // 增加了一個新功能:完成兩個數相加,然后和9求和 class B extends A { //這里,重寫了A類的方法, 可能是無意識 public int func1(int a, int b) { return a + b; } public int func2(int a, int b) { return func1(a, b) + 9; } }運行結果:

解決辦法
- 我們發現原來運行正常的相減功能發生了錯誤,原因就是類 B 無意中重寫了父類的方法,造成原有功能出現錯 誤,在實際編程中,我們常常會通過重寫父類的方法完成新的功能,這樣寫起來雖然簡單,但整個繼承體系的復用性會比較差,特別是運行多型比較頻繁的時候
- 通用的做法是:原來的父類和子類都繼承一個更通俗的基類,原有的繼承關系去掉,采用依賴,聚合,組合等 關系代替.
解決方案
package com.atguigu.principle.liskov.improve; public class Liskov { public static void main(String[] args) { // TODO Auto-generated method stub A a = new A(); System.out.println("11-3=" + a.func1(11, 3)); System.out.println("1-8=" + a.func1(1, 8)); System.out.println("-----------------------"); B b = new B(); //因為B類不再繼承A類,因此呼叫者,不會再func1是求減法 //呼叫完成的功能就會很明確 System.out.println("11+3=" + b.func1(11, 3));//這里本意是求出11+3 System.out.println("1+8=" + b.func1(1, 8));// 1+8 System.out.println("11+3+9=" + b.func2(11, 3)); //使用組合仍然可以使用到A類相關方法 System.out.println("11-3=" + b.func3(11, 3));// 這里本意是求出11-3 } } //創建一個更加基礎的基類 class Base { //把更加基礎的方法和成員寫到Base類 } // A類 class A extends Base { // 回傳兩個數的差 public int func1(int num1, int num2) { return num1 - num2; } } // B類繼承了A // 增加了一個新功能:完成兩個數相加,然后和9求和 class B extends Base { //如果B需要使用A類的方法,使用組合關系 private A a = new A(); //這里,重寫了A類的方法, 可能是無意識 public int func1(int a, int b) { return a + b; } public int func2(int a, int b) { return func1(a, b) + 9; } //我們仍然想使用A的方法 public int func3(int a, int b) { return this.a.func1(a, b); } }運行結果:

? 這篇博客是我在B站看韓順平老師設計模式的課時的筆記,記錄一下,防止忘記,也希望能幫助各位朋友,
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/514312.html
標籤:設計模式
上一篇:一篇文章帶你掌握主流辦公框架——SpringBoot
下一篇:里氏替換原則
