Liskovův substituční princip v TypeScriptu

Cílem tohoto principu je, aby podtřídy zůstaly kompatibilní s chováním nadřazené třídy. Podtřídy by měly rozšiřovat chování rodičovské třídy a ne ji nahrazovat něčím jiným.

Pokud se budete řídit tímto principem, budete moci nahradit nadřazenou třídu kteroukoli z jejích podtříd, aniž by došlo k porušení kódu klienta .

Představte si, že máme aplikaci, která přijímá objednávky. Pro objednávku existují dva možné stavy:koncept nebo potvrzeno. Pokud nebyla objednávka potvrzena, nelze ji zaplatit.

V následujícím příkladu porušujeme princip substituce, protože nadřazená třída má metodu markAsPaid který nevyvolává žádné chyby. Naopak podtřída DraftOrder vyvolá chybu v této metodě, protože koncept objednávek nelze zaplatit. Nahrazení nadřazené třídy Order podle jeho podtřídy DraftOrder může prolomit kód, pokud bychom volali markAsPaid .

class Order {
  id: number;
  items: string[];
  payed: boolean;

  // constructor

  markAsPaid(): void {
    this.payed = true;
  }
}

class DraftOrder extends Order {
  markAsPaid(): void {
    throw new Error("Draft orders can't be payed");
  }
}

Můžeme to zlepšit tím, že koncept objednávek uděláme nadřazenou třídou a potvrzené objednávky podtřídou. Tímto způsobem je možné nahradit nadřazenou třídu podtřídou bez porušení kódu.

class Order {
  id: number;
  items: string[];

  // constructor
}

class ConfirmedOrder extends Order {
  payed: boolean;

  // constructor

  markAsPaid(): void {
    this.payed = true;
  }
}