Development Notes/Terminology and Concepts

리스코프 치환 원칙(Liskov substitution principle)

Yongjae Kim 2024. 12. 8. 10:20
“자식 클래스는 부모 클래스로 교체해도 프로그램의 동작에 문제가 없어야 한다”

리스코프 치환 원칙 (Liskov Substitution Principle, LSP) 주요 특징

1. 서브타입의 대체 가능성

  • 자식 클래스(서브타입)는 부모 클래스(슈퍼타입)와 완전히 호환되어야 하며, 부모 클래스 대신 자식 클래스를 사용해도 프로그램이 정상적으로 동작해야 합니다.
  • 즉, 부모 클래스의 인스턴스가 필요한 모든 곳에서 자식 클래스 인스턴스를 대체할 수 있어야 합니다.

2. 행동 일관성 보장

  • 자식 클래스는 부모 클래스의 행동(메서드)을 변경하거나 예외를 추가하지 않고, 기존의 계약(Contract)을 그대로 따라야 합니다.
  • 부모 클래스가 특정 입력에 대해 예상되는 출력을 제공하면, 자식 클래스도 동일한 입력에 대해 일관된 출력을 제공해야 합니다.

3. 사전 조건 약화, 사후 조건 강화

  • 사전 조건(Precondition): 자식 클래스는 부모 클래스보다 더 엄격한 사전 조건을 요구해서는 안 됩니다.
  • 사후 조건(Postcondition): 자식 클래스는 부모 클래스보다 더 강력한 사후 조건을 제공할 수 있습니다.

4. 부모 클래스의 메서드와 일관된 반환 값

  • 부모 클래스의 메서드가 특정 타입의 값을 반환한다면, 자식 클래스도 동일한 타입 또는 그 서브타입을 반환해야 합니다.

5. 부모 클래스와 자식 클래스의 상태 일관성

  • 자식 클래스는 부모 클래스에서 정의된 속성과 상태를 변경해서는 안 됩니다.
  • 자식 클래스가 부모 클래스의 메서드를 재정의할 때, 기존의 동작을 위반하지 않고 확장해야 합니다.

 

예시

class Bird {
  fly(): void {
    console.log("Flying");
  }
}

class Penguin extends Bird {
  // 리스코프 치환 원칙 위반 예시
  fly(): void {
    throw new Error("Penguins can't fly!");
  }
}
  • Penguin은 Bird의 자식 클래스이지만, fly() 메서드를 재정의하여 예외를 발생시키므로 리스코프 치환 원칙을 위반합니다.
  • 이 문제를 해결하려면 Bird 클래스를 FlyingBird와 NonFlyingBird로 분리하여 더 명확한 타입 구조를 사용하는 것이 좋습니다.