开发者

Liskov's Substitution Principle - How to model Square and Rectangle [duplicate]

This question already has answers here: Closed 12 years ago.

Possible Duplicate:

Is deriving square from rectangle a violation of Liskov's Substitution Principle?

By applying the LSP, can anyone give me an implementation of Square and Rectangle?

I have read the book - "Head First开发者_Python百科 Object-Oriented Analysis and Design", they said if Sqaure inherit from Rectangle, it violated the LSP but does not have a proper implementation.

Anyone want a try?


If you make Square and Rectangle immutable, then you won't violate LSP.

The issue is if you can independently change the width and height of a Rectangle, and a Square is a Rectangle, then you can change a Square to not be a square.


I would say: Don't

A square is a special case of a rectangle. So: use rectangles. Its not clear that there is any good reason to have a distinct square class.

Of course, that really depends what you are doing with these shapes. Whether or not LSP is satisfied depends on the operations you have on your shapes.


You'd be better off with passing a constraint in the constructor (bool square would do) storing that as a field, and checking the fields (x, y, w, h?) during calculations for 'squareness' thus speeding elements of these calculations up.

You could make it so that if the 'square' constraint is set, setting width or height would cause the other one to match automatically. The set(x, y, w, h) method would always work, but would throw an IllegalArgumentException or such if the arguments didn't give a square.


If they are immutable, as stated above than it does not violate LSP:

public class Rectangle {
    int width;
    int height;

    public Rectangle(int w, int h) {
        width = w;
        height = h;
    }

    //getWidth(), getHeight, getArea(), etc, but no setters.
}


public Square extends Rectangle {
    public Square(int side) {
        super(side, side);
    }
}

Now if you had a scale() method that took a percentage you could grow the rectangle and square in an LSP-compliant way, but a grow() method on rectangle that took two sides that's overridden by square to behave correctly, of course, would violate LSP.


Clinton put it the best: it depends on what the definition of is is

The unshakable intuition that a square is a rectangle comes from our mathematical training. Mathematical objects are immutable and identity-less. If your program indeed is modeling square and rectangle objects in the mathematical sense, then Square should be a subtype of Rectangle, and they should be immutable. Any mathematical operations that applicable to Rectangle are applicable to Square.

However, your program may not be modeling mathematical objects. Maybe you are modeling graphic screen objects. There are mathematical aspects in them, but then there are more. Then we are in a mess. Maybe it's better to design Rectangle as subtype of Square, considering all the operations that you want to put on them. Then it's completely against our mathematical intuition, and we do not want that kind of confusion in our design.

This is a horrible truth: OOP is meh. You may have thought that some super smart people did some grandiose research and came up with this omnipotent programming model. For every puzzle there is a perfect solution, you just don't know it because you haven't become good enough in understanding this divine revelation. People argue about OOP with more zeal than religious enemies, throwing big words and abstract concepts at each other, quoting principles and conventions from ancient texts which nobody really understands.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜