2

There's a nice example of violating the Liskov Substitution Principle in the Circle-Ellipse Problem.

Here is how it is phrased (albeit in terms of Rectangle and Square) in a popular SO answer:

In mathematics, a Square is a Rectangle. Indeed it is a specialization of a rectangle. The "is a" makes you want to model this with inheritance. However if in code you made Square derive from Rectangle, then a Square should be usable anywhere you expect a Rectangle. This makes for some strange behavior.

Imagine you had SetWidth and SetHeight methods on your Rectangle base class; this seems perfectly logical. However if your Rectangle reference pointed to a Square, then SetWidth and SetHeight doesn't make sense because setting one would change the other to match it. In this case Square fails the Liskov Substitution Test with Rectangle and the abstraction of having Square inherit from Rectangle is a bad one.

My question is - Given a solution where we override setWidth in Square with an implementation that sets both width and height to the same value, why does it still violate LSP?

Community
  • 1
  • 1
urig
  • 16,016
  • 26
  • 115
  • 184

1 Answers1

3

It does violate it, because you promised setWidth() would set the width and setHeight() will set the height. The Square would break this (implicit) promise made by Rectangle.

Robert Bräutigam
  • 7,514
  • 1
  • 20
  • 38
  • 1
    Thanks. But anyone could argue that there is no such implicit promise, no? Where is it? Is it implied from the method name? – urig Mar 11 '18 at 13:20
  • 3
    Yes, it is implied by the name. It is pretty clear for anybody what you mean if you set the height of a rectangle, wouldn't you agree? I guess you could name the method `setWidthAndSometimesHeight()`, and it would be sort-of ok. But I think you feel that would be super weird.. – Robert Bräutigam Mar 11 '18 at 13:23
  • Would it be preferable to use a `SquareDecorator` with the `Rectangle` class to provide the `Square` functionality? – Reuel Ribeiro Jan 11 '19 at 16:29
  • 1
    I wouldn't call it a decorator, since it doesn't really preserve the original functionality. I would perhaps just create a `Square` that does not have a common ancestor with `Rectangle` at all. It depends on the use-case. – Robert Bräutigam Jan 11 '19 at 16:35