2011-03-30 3 views
48

나는 보통 객체 인스턴스가 Liskov Substitution Principle을 준수하는지 확인하려고 노력하지만, 나는 항상 LSP가 생성자에게도 적용되어야한다고 생각하는지 궁금해했다.생성자가 Liskov 대체 원칙을 준수해야합니까?

나는 이것에 대한 인터넷 검색을 시도했지만 어떤 강한 의견을 찾을 수 없었습니다.

코딩의 대부분은 Ruby에 있지만, 때로는 내 하위 클래스 생성자가 상위 클래스와 약간 다릅니다. 이들은 동일한 기본 인수 세트를 사용하며, 종종 추가 args를 사용합니다. 때로는 다른 클래스 메소드에서도 이와 같은 일이 발생합니다.

내 머리 뒤에서는 항상 LSP 위반 인 것처럼 느껴졌지 만 다른 사람이이 방법을 사용하고 있는지를 알고 싶었습니다.

답변

50

아니요, 생성자를 사용할 때 하위 유형을 처리하고 있다는 것을 알고 계실 것입니다. 따라서 다른 매개 변수와 같은 상위 생성자에 필수 조건이 아닌 전제 조건을 가질 수 있습니다. 대부분의 언어에서 생성자 이름이 생성되는 클래스의 이름이기 때문입니다.

ColoredSquareSquare의 적절한 하위 유형이 될 수있는 좋은 예이지만 추가 매개 변수 인 color이 필요합니다. 이 하위 유형과 같은 일을 할 수 없다면 훨씬 유용하지 않을 것입니다.

어떤 의미에서 생성자는 실제로 유형의 일부가 아닙니다. 해당 유형의 요소를 반환하는 함수입니다. 따라서 하위 유형에 대한 새 생성자를 정의해도 LSV가 중단되지 않습니다.

+5

"하위 유형을 처리하고 있다는 것을 알고있는 생성자를 사용할 때." 감사. 이것은 좋은 지적입니다. – Chance

+0

생성자, 정적 팩토리 메서드, 생성되는 형식의 인스턴스 인 팩터 리 메서드 (특히 Clone)와 다른 팩토리를 구별하는 것이 중요합니다. 정적 팩토리는 반환 유형에서 파생 된 여러 유형의 객체를 생성하지만 LSP는 생성 된 모든 객체에 적용해야합니다. 그러나 파생 클래스는 기본 클래스와 동일한 정적 메서드를 지원한다는 요구 사항은 없습니다. 클래스가 'Clone'과 같은 팩토리 메소드를 지원하면 LSP를 존중하고 하위 유형에서 유사한 의미를 지원해야합니다. – supercat

+0

다른 유형의 것을 반환하는 팩토리의 경우, 파생 팩토리에서 리턴 된 항목은 기본 팩토리에서 리턴 될 항목의 인스턴스로 사용할 수 있어야합니다. 따라서'CarFactory'가'Car'를 리턴하는'MakeCar()'메소드를 가지고 있고,'Drive()'메소드를 지원한다면, SomeCarFactory.MakeCar(). Drive()를 호출 할 수 있어야합니다. 'SomeCarFactory'는 실제로'FordFactory' ('CarFactory'를 상속받은)이며'Ford' ('Car'를 상속받은)를 반환합니다. – supercat

1

이것은 일종의 까다로운 질문이지만 필자가 글을 쓰는 경향이있는 방식으로 추가 매개 변수가 기능 변경에 전혀 영향을 미치지 않습니다. 내 생성자가 하위 클래스에서 추가 매개 변수를 필요로 할 때이 기능을 유지하면서 표준 기능을 유지해야한다는 것을 의미합니다. 그러나 ClassA = new ClassB (일부 args 포함)를 만들 수 있습니다. 그렇다면이 작업을 수행하든 ClassA = new ClassA()를 사용하든 관계없이 기능이 동일합니다. 일반적으로 일종의 Factory 메소드를 사용하여 작업 방법을 완벽하게 유지합니다. 다시 이것은 내가 어떻게 일을하는지, 일을하는 절대적인 올바른 방법이 아닙니다.

13

분명히 번호

생성자는 일반적으로 하위 유형에 특화되어 있습니다. 생성자에게 LSP를 적용하려고 시도하면 하위 유형이 특정 메소드 나 멤버를 추가 할 수 없다는 것과 같습니다. 그러나 제한은 다른 방향으로 만 존재합니다.

필자도 필자와 동의합니다. 생성자는 실제로 유형의 일부가 아닙니다. 일부 언어에서는 생성자 대신 다른 팩터를 쉽게 사용할 수 있습니다. Smalltalk 용어를 사용하면 생성자가 메타 클래스의 메소드라고 말할 수 있습니다.

여기 LSP를 위반하지 않고 클래스 메서드 (생성자 또는 다른 클래스 메서드)가 아닌 인스턴스 메서드에만 적용됩니다.