天天看點

設計模式-裡氏替換原則優點提供規範長方形是不是正方形總結為什麼要符合

設計模式-裡氏替換原則

優點

面向對象的語言繼承必不可少的,有如下優點

  1. 代碼共享,減少建立類的工作量
  2. 提高代碼的重用性
  3. 提高代碼的可擴充性
  4. 提高産品代碼的開放性
  5. 繼承侵入性 隻要繼承,必須擁有父類的内容
  6. 降低代碼的靈活性,子類必須擁有父類的屬性和方法
  7. 增強耦合性。

提供規範

裡氏替換原則,為繼承定義規範。

長方形是不是正方形

正方形是一種特殊的長方形,如果将正方形設計為長方形的子類,不符合裡氏替換原則

下方有三個類

類圖如下

設計模式-裡氏替換原則優點提供規範長方形是不是正方形總結為什麼要符合

關系如上所示

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;    // 可以通路基類繼承而來的,不能通路基類本身的,對同包内的可見,并且子類也可見
    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;
    }
}           

在上面的三塊代碼中,當調用SmartTest類的resize方法的時候,如果傳入的是父類,那麼将會可以的,如果傳入的是子類,正方形,那麼将會不可以的。

即。上方的為長方形行,正方形不行。

是以上面的栗子不符合裡氏替換原則。

解決方法,使用繼承時,要遵守裡氏替換原則,類B繼承類A時,不要重寫父類A的方法,也不能重載父類A的方法。

如果代碼更改如下更改

讓其兩個都共同定義同一個父類即可

其中最上層的類為兩個類的抽象類。

改進如下

設計模式-裡氏替換原則優點提供規範長方形是不是正方形總結為什麼要符合
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;
    }
}           

在上方的圖中,由于兩個為平級關系,是以父類的地方,換成子類也都可以。

總結

裡氏替換原則;父類可以的地方,換成子類也同樣可以。

為什麼要符合

一個栗子

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;    // 調用func1
    }
}           

在上方中,如果這樣書寫

package com.ming2;

public class Client {
    public static void main(String[] args) {
        B b = new B();
        System.out.println(b.func1(100, 50));
    }
}           

就違反了裡氏替換原則,即子類能使用的時候,父類也必須能使用。

www.iming.info

繼續閱讀