LSP原則—關於正方形不是長方形


長方形有二個屬性長和寬。並有一個設置長的方法和設置寬的方法,還有一個求面積的方法. 
像下面 
private int length; 
private int width; 
public void setLength(int lenght) { 
this.length = lenght; 

public void setWidth(int width) { 
this.width= width; 

public int getArea() { 
return this.length * this.width; 

如果說正方形是長方形的子類。為了保證正方形長和寬相等,那對應於正方形的二設置長寬的個方法就得改成 
public void setLength(int lenght) { 
this.length = lenght; 
this.width= lenght; 

public void setWidth(int width) { 
this.length = width; 
this.width= width; 

那我們想想用戶使用時候的情景。 我們都知道長方形的面積等於長與寬的積。那當我們用長方形的時候我們會這樣用 
Rectangle rectangle = new Rectangle(); 
rectangle.setLength(5); 
rectangle.setWidth(4); 
我們想知道面積是多少我們就可以 
rectangle.getArea(); 
得到的是20,當然結果是非常正確的。 
但想想如果我們把一個正方形的實例給用戶用的時候會怎么樣 
Rectangle rectangle = new Square(); //注意,這里體顯代換原則。用戶根本不知道真正的實例是正方形,用戶只知道長方形的事情。 
rectangle.setLength(5); 
rectangle.setWidth(4); 
我們想知道面積是多少我們就可以 
rectangle.getArea(); 
得到的結果卻是 16 ,這違背了長方形的面積是長與寬之積的原則。用戶就不會明白為什么我設置了長是5寬是4得到的答案卻是16 ?? 與前提不符 
所以正方形不能代替長方形出現在這個地方。 
也就是說正方形不應當看作是長方形的子類。

 

 

 之前人們討論的正方形長方形的問題的關鍵在哪里?我覺得就在於改動長方形的邊的長度。我們可以這么考慮一下,一個長方形的instance的邊長應該是可變的嗎?我覺得一旦一個長方形的邊長改變之后它就成了另一個長方形了(一個新的instance)。所以長方形類里面不應該有改變其邊長的方法,一個長方形實例各個的邊長應當在new它的時候確定下來,並且它們應當是immutable的。基於這種考慮,我設計的長方形和正方形的類如下所示:
//長方形
public class Rectangle {
  private final int width;
  private final int height;
  
  public Rectangle(int width, int height) {
    this.width = width;
    this.height = height;
  }
  
  public int getWidth() {
    return width;
  }

  public int getHeight() {
    return height;
  }
  
  public int getArea() {
    return width*height;
  }
}

//正方形
public class Square extends Rectangle{
  private final int side;
  
  public Square(int side) {
    super(side, side);
    this.side = side;
  }
  
  public int getSide() {
    return side;
  }
}

        這種繼承關系就既符合現實中的父子關系也遵循LSP。之所以這么設計,我的想法是一個類所具有的方法不應當能夠改變其本質。比如有一個Men類,它可以有eat(),sleep(),work(),makeLovewith(Person p)方法,但是如果你在里面定義denatureToWomen(),denatureToEunuch()就很不恰當了,因為這改變了其本質,導致這個Men的實例不再屬於Men類(至少已經和現實不吻合)了。除非這兩個方法不能改變該實例本質,否則在Men里面定義這兩個方法本身就是有問題的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM