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로 분리하여 더 명확한 타입 구조를 사용하는 것이 좋습니다.