Does this solve the Liskov Substitution square-rectangle violation?
liskov-substitution-principle, oop, solid-principles
Solution
Imagine the user is implementing a bounding box in a GUI application, similar to this:
They want to represent this blue box by a `Rectangle` class, so that if the user clicks & drags down its height will increase; if the user drags right, its width will increase.
LSP states that a client should be able to use a derived class (Square) wherever you would use its superclass (Rectangle) without breaking the business logic of Rectangle — i.e. a user should be able to sub in one for the other & the rest of their code shouldn't break.
But the following are incompatible with each other:
- It's an assumed post-condition of Rectangle that it's setter methods won't cause side effects (i.e. `setWidth` shouldn't affect the height)
- It's inherent to the logic of a Square that its width will always equal its height.
If the programmer used Square instead of Rectangle, their assumption above wouldn't work, as if the user dragged down, the box would get bigger horizontally & vertically at the same time.
The trouble with the Square/Rectangle example is that we're assuming too much about Rectangle to begin with. A rectangle can have a different length to its height, but this is a property of a specific type of rectangle (an oblong rectangle).
A square is a rectangle, but a square is not an oblong rectangle. If we want to assume the behaviour of an oblong about our `Rectangle` class (that it's width & height can differ), it's then doesn't make sense for our `Square` class to extend from that.
Problem
I'm very new to the SOLID design principles. One thing I had problem with understanding is the "Square-rectangle" example of a Liskov Substition Principle violation. Why should the Height/Width setter of a Square override the ones of a Rectangle? Isn't this exactly what's causing the problem when there's Polymorphism? Doesn't removing this solve the problem? ``` class Rectangle { public /*virtual*/ double Height { get; set; } public /*virtual*/ double Width { get; set; } public double Area() { return Height * Width; } } class Square : Rectangle { double _width; double _height; public /*override*/ double Height { get { return _height; } set { _height = _width = value; } } public /*override*/ double Width { get { return _width; } set { _width = _height = value; } } } class Program { static void Main(string[] args) { Rectangle r = new Square(); r.Height = 5; r.Width = 6; Console.WriteLine(r.Area()); Console.ReadLine(); } } ``` Output is 30 as expected.