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

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

关闭。这个问题是opinion-based .它目前不接受答案。












想改进这个问题?更新问题,以便 editing this post 可以用事实和引用来回答它.

8年前关闭。




Improve this question




考虑 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 的 child 可能会导致什么问题。但现在我学会了分辨它是否是紫色的语言服务商或不使用以下方式:

对于 square对象是 Square 的一个实例类(class),rectangle对象是 Rectangle 的一个实例类(class)
width=是两者中的一种方法
width=square无法替换为 width=rectangle
因为它不会像 'square' 中定义的那样设置高度。

我的这种思维方式错了吗?

而且我还学会了在 Rectangle 中使用紫罗兰色的 'width=' 方法。类来分析这个问题:

对于 width=在“矩形”类中

前置条件:@width@height有一定的值(value)。

后置条件:@width更改为新值,@height保持原样。

对于 Square 中的“宽度=”类(class)

前提:同上

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

根据原则:要求不多, promise 不少
@height已更改,因此未履行 promise ,因此不能继承

有没有人可以通过使用DBC给我一些关于我分析这个问题的方法的建议? ?

最佳答案

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

I can alway check the class of the object by using:

rectange.class

in this case, if the code in Ruby it will return Square so I won't treat it like Rectangle.


不是特定于 Ruby 的;事实上,您也可以在 Java 中检查变量的实际类。这样做并不能为这个问题提供“解决方案”。
这个例子的主要观察结果是,虽然正方形在几何上是矩形,但 Square不是 Rectangle从 OOP 的角度来看——一个 Square的行为与 Rectangle 的行为不兼容.

关于java - LSP 对像 Ruby 这样的动态类型语言也有意义吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17077097/

相关文章:

java - 如何从来自 api 响应的 json 字符串构造对象列表?

java - NetBeans : diamond operator is not supported in -source 1. 5(使用 -source 7 或更高版本启用菱形运算符)

java - 如何围绕已经存在但不能在java中修改的类创建接口(interface)

PHP - 静态类和缓存类

java - 使用 CSS 在 tabpane 中居中选项卡

java - 自定义 Maven 原型(prototype) : default value for version not used

Ruby - FlexMock 反引号方法

Ruby 1.8.7 将散列转换为字符串

ruby-on-rails - 守卫找不到 libnotify 也无法禁用通知但抛出错误

c++ - 创建给定模板的数组 (c++)