本文假定讀者已經(jīng)了解有關(guān)正方形不是長方形的相關(guān)內(nèi)容。
之前人們討論的正方形長方形的問題的關(guān)鍵在哪里?我覺得就在于改動長方形的邊的長度。我們可以這么考慮一下,一個長方形的instance的邊長應(yīng)該是可變的嗎?我覺得一旦一個長方形的邊長改變之后它就成了另一個長方形了(一個新的instance)。所以長方形類里面不應(yīng)該有改變其邊長的方法,一個長方形實例各個的邊長應(yīng)當(dāng)在new它的時候確定下來,并且它們應(yīng)當(dāng)是immutable的。基于這種考慮,我設(shè)計的長方形和正方形的類如下所示:
//長方形
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;
}
}
這種繼承關(guān)系就既符合現(xiàn)實中的父子關(guān)系也遵循LSP。之所以這么設(shè)計,我的想法是一個類所具有的方法不應(yīng)當(dāng)能夠改變其本質(zhì)。比如有一個Men類,它可以有eat(),sleep(),work(),makeLovewith(Person p)方法,但是如果你在里面定義denatureToWomen(),denatureToEunuch()就很不恰當(dāng)了,因為這改變了其本質(zhì),導(dǎo)致這個Men的實例不再屬于Men類(至少已經(jīng)和現(xiàn)實不吻合)了。除非這兩個方法不能改變該實例本質(zhì),否則在Men里面定義這兩個方法本身就是有問題的。不過如果用下面這種方式定義也許可行:
public Women denatureToWomen() {
Women w = new Women();
//set attributes here
return w;
}
public Eunuch denatureToEunuch() {
Eunuch e = new Eunuch();
//set attributes here
return e;
}
這樣一來,調(diào)用denatureToWomen()會產(chǎn)生一個新的實例,原來的那個Men實例依然存在,這和現(xiàn)實生活依然不吻合,現(xiàn)實生活中一個實例不光可以上型(upcast),還可以平行型,寒。。。
總之一句話,一個類的方法不應(yīng)該改變其實例的本質(zhì)。