我想說明與長方形和正方形的例子:爲什麼不可變對象允許遵守Liskov替換原則?
class Rectangle {
private int width;
private int height;
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public int area() {
return width * height;
}
}
class Square extends Rectangle{
@Override
public void setWidth(int width){
super.setWidth(width);
super.setHeight(width);
}
@Override
public void setHeight(int height){
super.setHeight(height);
super.setWidth(height);
}
}
public class Use {
public static void main(String[] args) {
Rectangle sq = new Square();
LSPTest(sq);
}
public static void LSPTest(Rectangle rec) {
rec.setWidth(5);
rec.setHeight(4);
if (rec.area() == 20) {
// do Something
}
}
}
如果我的方法替代的Square
而不是Rectangle
實例LSPTest我PROGRAMM的行爲將被改變。這與LSP是相反的。
我聽說,不可變對象允許解決這個問題。但爲什麼?
我改變了例子。 我Rectangle
添加構造函數:
public Rectangle(int width, int height) {
this.width = width;
this.height = height;
}
然後,我改變setter方法:
public Rectangle setWidth(int width) {
return new Rectangle(width, this.height);
}
public Rectangle setHeight(int height) {
return new Rectangle(this.width, height);
}
現在,Square
樣子:
class Square{
public Square() {
}
public Square(int width, int height) {
super(width, height);
}
@Override
public Rectangle setWidth(int width) {
return new Rectangle(width, width);
}
@Override
public Rectangle setHeight(int height) {
return new Rectangle(height, height);
}
}
這裏是客戶端代碼:
public class Use {
public static void main(String[] args) {
Rectangle sq = new Square(4, 4);
LSPTest(sq);
}
public static void LSPTest(Rectangle rec) {
rec = rec.setHeight(5);
if (rec.area() == 20) {
System.out.println("yes");
}
}
}
同樣的問題依然存在。對象本身是否發生更改或返回新對象有什麼區別。該程序對於基類和子類的行爲仍然不同。
是什麼讓你認爲不可變的對象固有地支持LSP? (提示,他們不)。 – jtahlborn
我同意@jtahlborn。試圖用一個返回一個新對象的setter來實現一個不可變對象似乎讓我感到困惑。 –
你的Square不可變的實現是這裏的問題。它的構造函數不應該有兩個參數,而只有一個參數。它不應該覆蓋setWidth和setHeight。基類setWidth()約定是返回一個具有與原始高度和給定寬度相同高度的Rectangle。沒有理由在Square中覆蓋它:base方法對於Square也是正確的:它只是不返回Square。 –