Site Tools


liskov-substitution-principle

Liskov substitution principle

The Liskov substitution principle (LSP) states that if S is a subtype of T, then objects of type T may be replaced with objects of type S without altering the correctness of the program. It was formulated by Barbara Liskov in a 1987 keynote. It is the L in SOLID.

The principle is about behavioural subtyping, not just structural subtyping. A subclass is allowed to extend a base class syntactically (override methods, add fields), but it must honour the contract of the base class: preconditions cannot be strengthened, postconditions cannot be weakened, and invariants must be preserved.

A classic violation

The textbook example is a Square extending Rectangle:

class Rectangle:
    def set_width(self, w):  self.width = w
    def set_height(self, h): self.height = h
    def area(self): return self.width * self.height
 
class Square(Rectangle):
    def set_width(self, w):
        self.width = w
        self.height = w   # square constraint: sides must be equal
    def set_height(self, h):
        self.width = h
        self.height = h

Code that works correctly with Rectangle will break with Square:

def scale_width(shape, factor):
    old_height = shape.height
    shape.set_width(shape.width * factor)
    assert shape.height == old_height   # FAILS for Square

The Rectangle contract says changing the width does not change the height. Square violates this. Substituting a Square for a Rectangle breaks the function, violating LSP.

Implication

LSP implies that inheritance should model an “is-a” relationship in terms of behaviour, not just structure. A square is geometrically a special case of a rectangle, but it is not a behavioural subtype of a mutable rectangle. The fix is either to make Rectangle immutable, or not to use inheritance here at all.

The principle guides when to use inheritance versus composition: if you cannot substitute freely, the “is-a” relationship is wrong and composition is likely better.

liskov-substitution-principle.txt · Last modified: by 127.0.0.1