設計模式-里氏替換原則
優(yōu)點
面向?qū)ο蟮恼Z言繼承必不可少的,有如下優(yōu)點
- 代碼共享,減少創(chuàng)建類的工作量
- 提高代碼的重用性
- 提高代碼的可擴展性
- 提高代碼的可擴展性
- 提高產(chǎn)品代碼的開放性
- 繼承侵入性 只要繼承,必須擁有父類的內(nèi)容
- 降低代碼的靈活性蔽豺,子類必須擁有父類的屬性和方法
- 增強耦合性。
提供規(guī)范
里氏替換原則,為繼承定義規(guī)范嘱蛋。
長方形是不是正方形
正方形是一種特殊的長方形,如果將正方形設計為長方形的子類五续,不符合里氏替換原則
下方有三個類
類圖如下
image
關系如上所示
package demo1;
public class SmartTest {
/*
* 長方形的長增加超過寬
*
* @param r
* */
public void resize(Rectangle r) {
while (r.getHeight() <= r.getWidth()) {
r.setHeight(r.getHeight() + 1);
}
}
}
package demo1;
/*
* 定義一個長方形類
* @author ming
* */
public class Rectangle {
protected long width; // 可以訪問基類繼承而來的洒敏,不能訪問基類本身的,對同包內(nèi)的可見疙驾,并且子類也可見
protected long height;
public void setWidth(long width) {
this.width = width;
}
public long getWidth() {
return this.width;
}
public void setHeight(long height) {
this.height = height;
}
public long getHeight() {
return this.height;
}
}
package demo1;
/*
* 定義一個正方形類繼承自長方形類
*
* @author ming
*
* */
public class Square extends Rectangle{
public void setWidth(long width, long height) {
this.width = width;
this.height = height;
}
public long getWidth() {
return width;
}
public void setHeight(long height, long width) {
this.height = height;
this.width = width;
}
public long getHeight() {
return height;
}
}
在上面的三塊代碼中凶伙,當調(diào)用SmartTest類的resize方法的時候,如果傳入的是父類它碎,那么將會可以的函荣,如果傳入的是子類,正方形扳肛,那么將會不可以的偏竟。
即。上方的為長方形行敞峭,正方形不行踊谋。
所以上面的栗子不符合里氏替換原則。
解決方法旋讹,使用繼承時殖蚕,要遵守里氏替換原則,類B繼承類A時沉迹,不要重寫父類A的方法睦疫,也不能重載父類A的方法。
如果代碼更改如下更改
讓其兩個都共同定義同一個父類即可
其中最上層的類為兩個類的抽象類鞭呕。
改進如下
image
package com.ming;
/*
* 定義一個四邊形類蛤育,只有get方法set方法
* @author ming
* */
public abstract class Quadrangle {
protected abstract long getWidth();
protected abstract long getHeight();
}
package com.ming;
public class Rectangle extends Quadrangle {
private long width;
private long height;
public void setWidth(long width) {
this.width = width;
}
public long getWidth() {
return this.width;
}
public void setHeight(long height) {
this.height = height;
}
public long getHeight() {
return this.height;
}
}
package com.ming;
public class Square extends Quadrangle{
private long width;
private long height;
public void setWidth(long width) {
this.height = width;
this.width = width;
}
public long getWidth() {
return this.,width;
}
public void setHeight(long height) {
this.height = height;
this.width = height;
}
public long getHeight() {
return this.height;
}
}
在上方的圖中,由于兩個為平級關系,所以父類的地方瓦糕,換成子類也都可以底洗。
總結(jié)
里氏替換原則;父類可以的地方咕娄,換成子類也同樣可以亥揖。
為什么要符合
一個栗子
package com.ming2;
public class A {
public int func1(int a, int b) {
return a-b;
}
}
package com.ming2;
public class B extends A{
public int func1(int a, int b) {
return a+b;
}
public int func2(int a, int b) {
return func1(a,b)+100; // 調(diào)用func1
}
}
在上方中,如果這樣書寫
package com.ming2;
public class Client {
public static void main(String[] args) {
B b = new B();
System.out.println(b.func1(100, 50));
}
}
就違反了里氏替換原則圣勒,即子類能使用的時候费变,父類也必須能使用。