Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I am new to design and learning the design principles.

It says deriving square from rectangle is a classic example of violation of Liskov's Substitution Principle.

If that's the case, what should be the correct design?

like image 572
somaraj Avatar asked Jun 23 '09 03:06

somaraj


People also ask

Which is a violation of the Liskov Substitution Principle?

A very common violation of this principle is the partial implementation of interfaces or base class functionality, leaving unimplemented methods or properties to throw an exception (e.g. NotImplementedException).

Which principle is violated when a square class extends the Rectangle class?

A classic example of violation of the Liskov Substitution Principle is the Rectangle - Square problem. The Square class extends the Rectangle class and assumes that the width and height are equal.

Which of the following from solid principles is a typical violation of LSP?

From Liskov Substitution Principle: 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. The Square class always assumes that the width is equal with the height.

Is a square substitutable for a rectangle?

Square is behaviorally not a correct substitution for Rectangle . A Square does not comply with the behavior of a rectangle: Changing the height/width of a square behaves differently from changing the height/width of a rectangle.


2 Answers

The answer depends on mutability. If your rectangle and square classes are immutable, then Square is really a subtype of Rectangle and it's perfectly OK to derive first from second. Otherwise, Rectangle and Square could both expose an IRectangle with no mutators, but deriving one from the other is wrong since neither type is properly a subtype of the other.

like image 112
Anton Tykhyy Avatar answered Sep 23 '22 11:09

Anton Tykhyy


I believe the reasoning is something like this:

Let's say you have a method that accepts a rectangle and adjusts its width:

public void SetWidth(Rectangle rect, int width) {     rect.Width = width; } 

It should be perfectly reasonable, given what a rectangle is, to assume that this test would pass:

Rectangle rect = new Rectangle(50, 20); // width, height  SetWidth(rect, 100);  Assert.AreEqual(20, rect.Height); 

... because changing a rectangle's width does not affect its height.

However, let's say you've derived a new Square class from Rectangle. By definition, a square has height and width always equal. Let's try that test again:

Rectangle rect = new Square(20); // both width and height  SetWidth(rect, 100);  Assert.AreEqual(20, rect.Height); 

That test will fail, because setting a square's width to 100 will also change its height.

Thus, Liskov's substitution principle is violated by deriving Square from Rectangle.

The "is-a" rule makes sense in the "real world" (a square is definitely a kind of rectangle), but not always in the world of software design.

Edit

To answer your question, the correct design should probably be that both Rectangle and Square derive from a common "Polygon" or "Shape" class, which does not enforce any rules regarding width or height.

like image 31
Matt Hamilton Avatar answered Sep 19 '22 11:09

Matt Hamilton