LSP对像Ruby这样的动态类型语言也有意义吗?

时间:2013-06-12 23:33:08

标签: java ruby oop design-by-contract liskov-substitution-principle

考虑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=中的square中的width=无法替换为rectangle中的Rectangle

因为它不会将高度设置为'square'中定义的高度。

这种思维方式我错了吗?

此外,我学会了使用紫罗兰width=类中'width ='方法的联系来分析这个问题:

对于'Rectangle'类

中的@width

前提条件:@height@width有一些价值。

postconditon:@height更改为新值,Square保持不变。

表示@height

中的'width ='

前提条件:与上述相同

postconditon:'@ width'更改为新值, @height更改为新值

根据原则:不再需要,承诺不少

DBC已更改,因此未履行承诺,因此无法继承

有没有人可以通过{{1}}?

给我一​​些关于我分析此问题的方法的建议

1 个答案:

答案 0 :(得分:2)

LSP仍然适用,即使在像Ruby这样的动态类型语言中也是如此。你的推理:

  

我总是可以使用以下方法检查对象的类:

rectange.class
     

在这种情况下,如果Ruby中的代码将返回Square,那么我不会将其视为Rectangle

不是特定于Ruby;实际上,您也可以在Java中检查变量的实际类。这样做并不能解决这个问题。

此示例的关键观察是,虽然正方形是几何体中的矩形,但从OOP角度来看,Square 不是 Rectangle - { {1}}的行为与Square的行为不相容。