Square和Rectangle继承有什么问题? [英] What's wrong with the Square and Rectangle inheritance?

查看:350
本文介绍了Square和Rectangle继承有什么问题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经阅读了一些有关将Square设为Rectangle类的继承类的做法的坏习惯,因为它违反了LSP(Liskov替换原理).我还是不明白,我用Ruby编写了一个示例代码:

I've read some of article about the practice that making Square an inheritance class of Rectangle class is a bad practice, saying it violate the LSP (Liskov substitution principle). I still don't get it, I made a example code in Ruby:

class Rectangle
    attr_accessor :width, :height
    def initialize(width, height)
        @width = width
        @height = height
    end
end

class Square < Rectangle
    def initialize(length)
        super(length, length)
    end
    def width=(number)
        super(number)
        @height = number
    end

    def height=(number)
        super(number)
        @width = number
    end
end


s = Square.new(100)

s.width = 50

puts s.height

谁能告诉我这是怎么回事?

Could anyone tell me what's wrong with it?

推荐答案

我并不总是热衷于Liskov,因为它似乎限制了基于行为而不是本质"的继承行为.在我看来,继承始终被认为是一种是"关系,而不是一种行为完全相同".

I'm not always keen on Liskov since it seems to limit what you can do with inheritance based on behaviour rather than "essence". In my view, inheritance was always meant to be an "is a" relationship, not an "acts exactly like" one.

话虽如此,维基百科文章详细介绍了为什么 使用您的确切示例,这被某些人认为是不好的:

Having said that, the wikipedia article goes into detail as to why this is considered bad by some, using your exact example:

一个违反LSP的典型示例是从Rectangle类派生的Square类,假定宽度和高度都存在getter和setter方法.

A typical example that violates LSP is a Square class that derives from a Rectangle class, assuming getter and setter methods exist for both width and height.

Square类始终假定宽度等于高度.如果在需要Rectangle的上下文中使用Square对象,则可能会发生意外行为,因为Square的尺寸不能(或应该不应该)单独修改.

The Square class always assumes that the width is equal with the height. If a Square object is used in a context where a Rectangle is expected, unexpected behavior may occur because the dimensions of a Square cannot (or rather should not) be modified independently.

这个问题不能轻易解决:如果我们可以在Square类中修改setter方法,使其保留Square不变(即,保持尺寸相等),那么这些方法将削弱(违反)Rectangle的后置条件设置器,声明可以单独修改尺寸.

This problem cannot be easily fixed: if we can modify the setter methods in the Square class so that they preserve the Square invariant (i.e., keep the dimensions equal), then these methods will weaken (violate) the postconditions for the Rectangle setters, which state that dimensions can be modified independently.

因此,将您的代码与等效的Rectangle代码一起查看:

So, looking at your code alongside the equivalent Rectangle code:

s = Square.new(100)            r = Rectangle.new(100,100)
s.width = 50                   r.width = 50
puts s.height                  puts r.height

输出将在左侧为50,在右侧为100.

the output would be 50 on the left and 100 on the right.

但是,在我看来,是本文中的重要内容:

But, this is the important bit from the article, in my view:

像这样的违反LSP的行为,可能会或可能不会在实践中会成为问题,这取决于使用违反LSP的类的代码实际预期的后置条件或不变式.

Violations of LSP, like this one, may or may not be a problem in practice, depending on the postconditions or invariants that are actually expected by the code that uses classes violating LSP.

换句话说,只要使用类的代码能理解行为,就没有问题.

In other words, provided the code using the classes understands the behaviour, there is no issue.

底线,正方形是矩形的适当子集,用于对矩形的宽松定义:-)

Bottom line, a square is a proper subset of a rectangle, for a loose-enough definition of rectangle :-)

这篇关于Square和Rectangle继承有什么问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆