0

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か?

4

1 に答える 1

2

Ruby のような動的型付け言語でも、LSP は引き続き適用されます。あなたの推論:

以下を使用して、オブジェクトのクラスをいつでも確認できます。

rectange.class

この場合、Ruby のコードなら返ってくるSquareので、 のようには扱いませんRectangle

Ruby に固有のものではありません。実際、Java で変数の実際のクラスを確認することもできます。そうしても、この問題の「解決策」にはなりません。

この例の重要な観察結果は、正方形はジオメトリの長方形ですが、OOP の観点からは aSquare ではないということです。a の動作は aの動作と互換性がありません。RectangleSquareRectangle

于 2013-06-13T00:04:45.347 に答える