> For the complete documentation index, see [llms.txt](https://khaled-hamam.gitbook.io/design-patterns-explained/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://khaled-hamam.gitbook.io/design-patterns-explained/solid-principles/liskov-substitution.md).

# Liskov Substitution Principle

![Liskov Substitution Principle](https://user-images.githubusercontent.com/24835522/98735423-02028a00-23ac-11eb-9743-4ab6797d6560.png)

**Definition:** Subtypes must be completely substitutable for their base types.

**Substitutability Rules:**

1. Child class mustn't remove a base class behavior.
2. Child class mustn't violate base class objects (manipulated behavior).
3. Inheritance can be described as *IS A* but Liskov says it should be described as *IS Substitutable For*.
4. There’s no problem if the child class has extra members but it should not be less (have members with no use or with manipulated behavior).

## Example

![Example UML](https://user-images.githubusercontent.com/24835522/98862198-2d9a7880-246f-11eb-8757-16b54ed50be7.png)

```typescript
interface Shape {
  setWidth(value): void;
  setHeight(value): void;
  getArea(): number;
}

class Rectangle implements Shape {
  private _width: number;
  private _height: number;

  public setWidth(value) {
    this._width = value;
  }

  public setHeight(value) {
    this._height = value;
  }

  public getArea() {
    return this._width * this._height;
  }
}

class Square implements Shape {
  private _sideLength: number;

  public setWidth(value) {
    this._sideLength = value;
  }

  public setHeight(value) {
    this._sideLength = value;
  }

  public getArea() {
    return this._sideLength * this._sideLength;
  }
}
```

One of the most famous examples of violating Liskov is when dealing with logical hierarchies in code. We usually want to make an interface Shape that Rectangle, Square, and even Circle will implement. Although this may make sense logically as they're all shapes, they differ greatly in behavior and can't be substituted without violating LSP.

Square has a Width equal to its Height, so when setting one of them we're also setting the other, but of course this is not explicit for the user of the code and may lead to faulty results.

## Solution

![Solution UML](https://user-images.githubusercontent.com/24835522/98862291-4f93fb00-246f-11eb-97d4-6f28d0f059b0.png)

```typescript
interface Shape {
  getArea(): number;
}

class Rectangle implements Shape {
  private _width: number;
  private _height: number;

  public setWidth(value) {
    this._width = value;
  }

  public setHeight(value) {
    this._height = value;
  }

  public getArea() {
    return this._width * this._height;
  }
}

class Square implements Shape {
  private _sideLength: number;

  public setSideLength(value) {
    this._sideLength = value;
  }

  public getArea() {
    return this._sideLength * this._sideLength;
  }
}
```

Now we kept only the real common methods in the interface of Shape, which is *getArea()* in our case, and now the code returned to be completely substitutable again without any violations for LSP, and without any unexpected behaviors.

Of course in other examples there may be no common methods, then we need to rethink why we want to group them together in the first place.
