Java の古典的な例を考えてみましょう
// Violation of Likov's Substitution Principle
class Rectangle
{
protected int m_width;
protected int m_height;
public void setWidth(int width){
m_width = width;
}
public void setHeight(int height){
m_height = height;
}
public int getWidth(){
return m_width;
}
public int getHeight(){
return m_height;
}
public int getArea(){
return m_width * m_height;
}
}
class Square extends Rectangle
{
public void setWidth(int width){
m_width = width;
m_height = width;
}
public void setHeight(int height){
m_width = height;
m_height = height;
}
}
class LspTest
{
private static Rectangle getNewRectangle()
{
// it can be an object returned by some factory ...
return new Square();
}
public static void main (String args[])
{
Rectangle r = LspTest.getNewRectangle();
r.setWidth(5);
r.setHeight(10);
// user knows that r it's a rectangle.
// It assumes that he's able to set the
// width and height as for the base class
System.out.println(r.getArea());
// now he's surprised to see that the area is 100 instead of 50.
}
}
Javaのような静的型付き言語の親クラスのように、子クラスのオブジェクトを処理できる(型キャスト?)ことが要点だと思います:
Rectange rectange = new Square();
しかし、Rubyでは意味がないと思います.Rubyでも同じです:
class Rectangle
attr_accessor :width, :height
def getArea()
@width * @height
end
end
class Square < Rectangle
def width=(number)
super(number)
@height = number
end
def height=(number)
super(number)
@width = number
end
end
s = Square.new(100)
puts s.class
s.width = 50
puts s.height
次を使用して、オブジェクトのクラスをいつでも確認できます。
rectange.class
この場合、Ruby のコードが返される場合Square
のようには扱いませんRectange
。
Ruby のような動的型付け言語で LSP を適用するポイントを誰か説明してもらえますか?
SquareをRectangleの子にすることがどのような問題を引き起こす可能性があるかはまだわかりませんが。しかし今では 、次の方法を使用して、 LSPをバイオレット化するかどうかを確認することを学びます。
square
オブジェクトはSquare
クラスのインスタンスであり、オブジェクトrectangle
はクラスのインスタンスRectangle
です
これwidth=
は両方のメソッドです
width=
inをinsquare
に置き換えることはできませんwidth=
rectangle
「正方形」で定義されているように高さを設定しないためです。
この考え方は間違っていますか?
また、Rectangle
クラスで 'width=' メソッドのバイオレットを使用して、この問題を分析することも学びました。
width=
「Rectangle」クラスの
前提条件:@width
そして、@height
何らかの価値があります。
事後条件:@width
新しい値に変更し、その@height
ままにしておきます。
Square
クラスの「幅=」
前提条件:上と同じ
事後条件: '@width' を新しい値に@height
変更、新しい値に変更
原則に従って:それ以上は要求せず、それ以下は約束しない
が@height
変更されたため、約束が果たされないため、継承できません
を使用してこの問題を分析する方法について、誰かがアドバイスをくれますDBC
か?