假設有一個函數f,它的參數爲指向某個基類B的指針或引用,同樣假設存在B的某個派生類D,如果把D的對象作爲
B類型傳給f,會導致f出現錯誤的行爲,那麼D就違反了LSP
Martin 舉了個例子:
public class Rectangle()
{
private int width;
private int height;
public void setWidth(int w)
{
this.width = w;
}
public void setHeight(int h)
{
this.height = h;
}
public int getArea()
{
return this.height * this.width;
}
}
很自然的Square從Rectangle繼承而來,但是重寫了兩個方法,保證長和寬是一致的
public class Square extend Rectangle()
{
public void setWidth(int w)
{
super.setWidth(w);
super.setHeight(w);
}
public void setHeight(int h)
{
super.setWidth(h);
super.setHeight(h);
}
}
假設有下面的函數g
void g(Rectangle r)
{
r.setWidth(5);
r.setHeight(4);
assert(r.getArea() == 20);
}
當傳進來的對象是square時就會發生錯誤!!!這裏就違反了Lsp
基於DBC的設計:前置條件,後置條件,不變式(參見Meyer的書籍《基於DBC的設計》)
Lsp使得OCP成爲可能,子類型對父類型的可替換性必須是開發人員可以隱式依賴的東西,因此,如果沒有顯式的強制基類類型的契約,那些代碼就必須良好並且明顯的表達出這一點。