Search code examples
oopliskov-substitution-principle

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


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?


Solution

  • 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.