Skip to main content

Liskov Substitution Principle

  • Objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program.
  • In other words, if S is a subtype of T, then objects of type T may be replaced with objects of type S without altering any of the desirable properties of the program.
  • The Liskov Substitution Principle (LSP) is a particular definition of a subtyping relation, called (strong) behavioral subtyping.
  • LSP is a semantic rather than merely syntactic relation because it intends to guarantee semantic interoperability of types in a hierarchy, object types in particular.
// Liskov Substitution Principle
class Rectangle {
constructor(width, height) {
this.width = width;
this.height = height;
}

setWidth(width) {
this.width = width;
}

setHeight(height) {
this.height = height;
}

area() {
return this.width * this.height;
}
}

// when we add a new shape, we don't need to modify the Rectangle class
// but the Square class violates the Liskov Substitution Principle
// because the Square class does not behave as the Rectangle class
// the Square class should not inherit from the Rectangle class
// the Square class should inherit from the Shape class
class Square extends Rectangle {
constructor(length) {
super(length, length);
}

setWidth(width) {
this.width = width;
this.height = width;
}

setHeight(height) {
this.width = height;
this.height = height;
}
}

const useIt = (rectangle) => {
const width = rectangle.width;
rectangle.setHeight(10);
// area is 100, not 200, because the Square class violates the Liskov Substitution Principle
console.log(`Expected area of ${10 * width}, got ${rectangle.area()}`);
};

const rectangle = new Rectangle(2, 3);

// Expected area of 20, got 20
useIt(rectangle);

const square = new Square(5);

// Expected area of 50, got 100, because the Square class violates the Liskov Substitution Principle
useIt(square);