아마도 당신은 사람들이 지난 몇 개월 동안 이것을 말한 것을 보았지만, 그보다 훨씬 더 좋은 프로그래머에게 알려져 있습니다. 나는 약 10 년 동안 적절한 곳에서 분명히 말하고 있습니다.
개념의 요점은 상속에 대한 개념적 오버 헤드가 크다는 것입니다. 상속을 사용할 때 모든 단일 메소드 호출에는 암시 적 디스패치가 있습니다. 깊은 상속 트리 또는 다중 디스패치가 있거나 (또는 더 나쁜 경우) 둘 다있는 경우 특정 호출에서 특정 메소드가 어디로 디스패치되는지 파악하면 왕실 PITA가 될 수 있습니다. 코드에 대한 올바른 추론을 더 복잡하게 만들고 디버깅을 더 어렵게 만듭니다.
간단한 예를 들어 설명하겠습니다. 상속 트리에서 누군가 이름을 method라고하자 foo
. 그런 다음 다른 사람이 와서 foo
나무 꼭대기에 추가 하지만 다른 일을합니다. (이 경우는 다중 상속에서 더 흔합니다.) 이제 루트 클래스에서 일하는 사람이 모호한 하위 클래스를 깨뜨 렸고 아마도이를 인식하지 못했을 것입니다. 단위 테스트를 100 % 적용 할 수 있으며 최상위에있는 사람은 하위 클래스 테스트를 생각하지 않으며 하위 클래스 테스트는 상위에서 작성된 새 메소드를 테스트하지 않기 때문에이 파손을 알 수 없습니다. . (이를 잡아주는 단위 테스트를 작성하는 방법이 있지만, 그렇게 쉽게 테스트를 작성할 수없는 경우도 있습니다.)
반대로 컴포지션을 사용할 때 각 통화마다 통화를 전달하는 것이 더 명확합니다. (예를 들어, 의존성 주입과 같은 제어 역전을 사용하는 경우 호출이 진행되는 위치를 파악하는 것도 문제가 될 수 있지만 일반적으로 알아내는 것이 더 간단합니다.) 이렇게하면 추론이 쉬워집니다. 보너스로, 컴포지션은 메소드를 서로 분리시킵니다. 위의 예제는 자식 클래스가 모호한 구성 요소로 이동하기 때문에 발생하지 않아야하며 호출 foo
이 모호한 구성 요소 또는 주 개체에 대한 것인지 여부에 대한 질문은 없습니다 .
상속과 구성은 서로 다른 두 가지 유형의 서비스를 제공하는 두 개의 매우 다른 도구라는 것이 옳습니다. 물론 상속은 개념적 오버 헤드를 가져 오지만 그것이 작업에 적합한 도구 인 경우에는 사용하지 않고 손으로하는 일보다 개념적 오버 헤드가 줄어 듭니다. 그들이하는 일을 아는 사람은 결코 상속을 사용해서는 안된다고 말하지 않을 것입니다. 그러나 그것이 옳은 일인지 확인하십시오.
불행히도 많은 개발자는 객체 지향 소프트웨어에 대해 배우고 상속에 대해 배우고 가능한 한 자주 새로운 도끼를 사용합니다. 즉, 컴포지션이 올바른 도구 인 상속을 사용하려고합니다. 그들은 시간이 지남에 따라 더 잘 배우기를 희망하지만, 사지 등을 몇 개 제거한 후에야 종종 이런 일이 발생하지 않습니다. 나쁜 생각이라고 미리 말하는 것은 학습 과정의 속도를 높이고 부상을 줄이는 경향이 있습니다.