前言
本博主將用CSDN記錄軟件開發(fā)求學之路上親身所得與所學的心得與知識,有興趣的小伙伴可以關注博主!也許一個人獨行,可以走的很快,但是一群人結伴而行,才能走的更遠!
一、 介紹
(1)引入
繼承包含這樣一層含義:父類中凡是已經實現好的方法,實際上是在設定規(guī)范和契約,雖然它不強制要求所有的子類必須遵循這些契約,但是如果子類對這些已經實現的方法任意修改,就會對整個繼承體系造成破壞。
繼承在給程序設計帶來便利的同時,也帶來了弊端。
比如:
● 使用繼承會給程序帶來侵入性;
● 程序的可移植性降低;
● 增加對象間的耦合性;
● 如果一個類被其他的類所繼承,則當這個類需要修改時,必須考慮到所有的子類,并且父類修改后,所有涉及到子類的功能都有可能產生故障問題提出:在編程中,如何正確的使用繼承? => 里氏替換原則
(2)基本介紹
里氏替換原則(LSP)在1988年,由麻省理工學院的以為姓里的女士提出的。
如果對每個類型為T1的對象o1,都有類型為T2的對象o2,使得以T1定義的所有程序P在所有的對象o1都代換成o2時,程序P的行為沒有發(fā)生變化,那么類型T2是類型T1 的子類型。換句話說,所有引用基類的地方必須能透明地使用其子類的對象。
在使用繼承時,遵循里氏替換原則,在子類中盡量不要重寫父類的方法。文章來源:http://www.zghlxwxcb.cn/news/detail-457245.html
里氏替換原則告訴我們,繼承實際上讓兩個類耦合性增強了,在適當的情況下,可以通過聚合,組合,依賴來解決問題。文章來源地址http://www.zghlxwxcb.cn/news/detail-457245.html
二、代碼演示
1、版本一:原始版本
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;
}
}
- 我們發(fā)現原來運行正常的相減功能發(fā)生了錯誤。原因就是類B無意中重寫了父類的方法,造成原有功能出現錯誤。在實際編程中,我們常常會通過重寫父類的方法完成新的功能,這樣寫起來雖然簡單,但整個繼承體系的復用性會比較差。特別是運行多態(tài)比較頻繁的時候。
- 通用的做法是:原來的父類和子類都繼承一個更通俗的基類,原有的繼承關系去掉,采用依賴,聚合,組合等關系代替。
2、版本二:里氏替換原則
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
}
}
//創(chuàng)建一個更加基礎的基類
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);
}
}
到了這里,關于設計模式:里氏替換原則(詳解)的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!