Sublcass는 부모의 행동을 변경해서는 안됩니까?
그것은 LSP에 대한 일반적인 오해입니다. 서브 클래스는 부모 유형에 충실한 한 부모의 동작을 변경할 수 있습니다.
Wikipedia에 대한 자세한 설명이 있으며 LSP를 위반할 사항을 제안합니다.
하위 유형이 충족해야하는 여러 가지 행동 조건이 있습니다. 이것들은 계약 방법론에 의한 디자인의 용어와 유사한 용어에 자세히 설명되어 있으며, 계약이 상속과 상호 작용하는 방법에 대한 몇 가지 제한을 초래합니다.
- 하위 유형에서는 전제 조건을 강화할 수 없습니다.
- 하위 유형에서는 사후 조건을 약화시킬 수 없습니다.
- 상위 유형의 변형은 하위 유형으로 유지되어야합니다.
- 히스토리 제한 사항 ( "히스토리 규칙"). 객체는 그 방법 (캡슐화)을 통해서만 수정 가능한 것으로 간주됩니다. 서브 타입은 수퍼 타입에 존재하지 않는 메소드를 도입 할 수 있기 때문에, 이러한 메소드의 도입은 수퍼 타입에 허용되지 않는 서브 타입의 상태 변경을 허용 할 수 있습니다. 히스토리 제한은이를 금지합니다. Liskov와 Wing이 소개 한 새로운 요소였습니다. MutablePoint를 ImmutablePoint의 하위 유형으로 정의하여이 제약 조건을 위반하는 것을 예로들 수 있습니다. 이것은 불변 지점의 이력에서 생성 후 상태가 항상 동일하므로 일반적으로 MutablePoint의 이력을 포함 할 수 없기 때문에 이력 제약 조건을 위반하는 것입니다. 그러나 하위 유형에 추가 된 필드는 수퍼 유형 메소드를 통해 관찰 할 수 없으므로 안전하게 수정할 수 있습니다.
개인적으로, 나는 이것을 간단히 기억하는 것이 더 쉽다는 것을 안다 : 타입 A가있는 메소드의 매개 변수를보고 있다면 하위 유형 B를 전달하는 누군가 나를 놀라게 할 것인가? 그렇다면 LSP를 위반 한 것입니다.
예외를 던지는 것은 놀라운 일입니까? 실제로는 아닙니다. OrderState에서 Ship 메소드를 호출하든 Granted 또는 Shipped에서 호출하든 관계없이 언제든지 발생할 수 있습니다. 그래서 나는 그것을 설명해야하며 실제로 LSP의 위반이 아닙니다.
즉 , 나는이 상황을 처리하는 더 좋은 방법이 있다고 생각합니다. C #으로 이것을 작성한다면 인터페이스를 사용하고 메소드를 호출하기 전에 인터페이스의 구현을 확인합니다. 예를 들어, 현재 OrderState가 IShippable을 구현하지 않으면 Ship 메소드를 호출하지 마십시오.
그러나이 특정 상황에서는 State 패턴을 사용하지 않을 것입니다. 상태 패턴은 이와 같은 도메인 개체의 상태보다 응용 프로그램의 상태에 훨씬 더 적합합니다.
간단히 말해서, 이것은 상태 패턴에 대해 잘 고안되지 않은 예이며 주문 상태를 처리하는 특히 좋은 방법은 아닙니다. 그러나 LSP를 위반하지는 않습니다. 그리고 국가 패턴 자체는 확실히 그렇지 않습니다.