【SOLID原則】リスコフの置換原則とは何か

2023/02/26に公開約1,600字

リスコフの置換原則

リスコフの置換原則は、LSP(Liskov Substitution Principle)とも呼ばれます。

SOLID原則のLにあたる部分です。

リスコフの置換原則は、サブタイプは、常にその基本型に置き換えることができるという原則です。

つまり、あるクラスを利用している場所に、そのクラスのサブクラスを置き換えても、プログラム全体の動作に影響がないようにすることが重要です。

すなわち以下の挙動にすべきということです。

  • 子クラスでオーバーライドしたメソッドは、親クラスのメソッドと同様の引数を取り、同じ型の返り値を返さなければいけない。

たとえば、以下例ではリスコフの置換原則に違反しています

悪いコード(原則に反している)

class Rectangle {
  constructor(public width: number, public height: number) {}

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

class Square extends Rectangle {
  constructor(public size: number) {
    super(size, size);
  }
}

function printArea(rectangle: Rectangle) {
  console.log(rectangle.area());
}

const rectangle = new Rectangle(10, 5);
const square = new Square(10);

printArea(rectangle); // 50
printArea(square); // 100

この例では、SquareクラスがRectangleクラスを継承していますが、Squareクラスには新しいプロパティであるsizeがあります。そのため、SquareクラスのインスタンスをRectangleクラスのインスタンスとして扱うことができません。

良いコード例(原則に則している)

これを解決するためには、SquareクラスをRectangleクラスから分離することができます。例えば、以下のようにすることができます。

abstract class Shape {
  abstract area(): number;
}

class Rectangle extends Shape {
  constructor(public width: number, public height: number) {
    super();
  }

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

class Square extends Shape {
  constructor(public size: number) {
    super();
  }

  area(): number {
    return this.size ** 2;
  }
}

function printArea(shape: Shape) {
  console.log(shape.area());
}

const rectangle = new Rectangle(10, 5);
const square = new Square(10);

printArea(rectangle); // 50
printArea(square); // 100

このようにすることで、SquareクラスのインスタンスをRectangleクラスのインスタンスとして扱うことができます。つまり、リスコフの置換原則に違反していないということになります。

Discussion

ログインするとコメントできます