프로그래밍 언어에서, 모든 클래스와 인터페이스가 인터페이스만 상속받을 수 있다고 하자. 이에 더해, 코드 재사용을 상속 대신 컴포지션으로 해결하도록 강제하자. 이 때, 상속의 문제점 중 어떤 게 왜 해결될까? 해결되지 않는 문제가 존재한다면 왜 그런 걸까?
상속의 문제점 중 해결될 것으로 예상되는 몇 가지 문제점이 있습니다.

1. 다양한 클래스의 결합도 감소: 상속을 사용하면 클래스 간의 결합도가 높아지기 쉽습니다. 하지만 인터페이스로만 상속을 받도록 강제하면 클래스 간의 결합도를 낮출 수 있습니다. 인터페이스는 구현에 대한 세부 사항을 알지 못하므로 클래스 간의 결합도를 줄여줍니다.

2. 다형성의 확장: 객체 지향 프로그래밍에서 다형성은 매우 중요한 개념입니다. 상속을 사용하면 클래스 간의 다형성을 확장하는 데 어려움을 겪을 수 있습니다. 하지만 인터페이스로만 상속을 받는다면 인터페이스의 구현을 다양한 클래스에서 재사용할 수 있으므로 다형성을 보다 쉽게 확장할 수 있습니다.

3. 코드의 유연성 향상: 상속은 코드의 유연성을 떨어뜨릴 수 있습니다. 상속을 사용하면 상위 클래스의 변경 사항이 하위 클래스에 영향을 줄 수 있습니다. 하지만 인터페이스로만 상속을 받는다면 클래스와 인터페이스 간의 결합도를 낮추고 코드의 유연성을 향상시킬 수 있습니다.

그러나 상속을 대체할 수 있는 컴포지션도 몇 가지 단점이 있을 수 있습니다.

1. 코드 재사용의 어려움: 상속을 통해 코드를 재사용하는 것은 상속 자체에 비해 상대적으로 쉽습니다. 하지만 컴포지션을 사용하면 코드를 재사용하는 것이 더 복잡하고 번거롭게 될 수 있습니다.

2. 성능 저하: 컴포지션을 사용하면 여러 객체의 인스턴스를 생성하고 관리해야 합니다. 이는 상속에 비해 추가적인 오버헤드가 발생할 수 있으며, 성능에 영향을 줄 수 있습니다.

따라서, 상속의 문제점을 해결하기 위해서는 인터페이스를 사용하면서 컴포지션을 적절하게 활용하는 것이 좋습니다. 이를 통해 코드의 유연성과 재사용성을 높일 수 있으며, 성능 저하를 최소화할 수 있습니다.
프로그래밍에서 상속 대신 컴포지션을 선호하는 접근 방식은 다양한 문제를 해결할 수 있지만, 일부 문제는 여전히 남아 있을 수 있습니다. 클래스와 인터페이스가 인터페이스만 상속받을 수 있으며, 코드 재사용을 컴포지션으로 해결한다고 가정했을 때, 해결되는 문제점들과 여전히 남아 있는 문제점을 살펴보겠습니다.

### 해결되는 문제점

1. **강한 결합도 (Tight Coupling) 감소**: 상속은 부모 클래스와 자식 클래스 간의 강한 결합을 만들어낼 수 있습니다. 컴포지션을 사용하면, 객체들이 더 유연하게 협력하게 되며, 결합도가 낮아지고, 코드의 재사용성과 유지보수성이 향상됩니다.

2. **상속 다이아몬드 문제 해결**: 다중 상속 시 발생할 수 있는 다이아몬드 문제가 인터페이스 상속에서는 발생하지 않습니다. 클래스들이 인터페이스만 상속받는 경우, 구현이 중복되지 않으므로, 상속으로 인한 모호성이나 중복 문제가 발생하지 않습니다.

3. **리스코프 치환 원칙 (LSP) 위배 감소**: 상속을 사용할 때, 부모 클래스 대신 자식 클래스를 사용하더라도 시스템이 정상적으로 작동해야 한다는 리스코프 치환 원칙을 위배하는 경우가 발생할 수 있습니다. 컴포지션을 사용하면, 이러한 위배 가능성이 줄어듭니다.

### 여전히 남아있는 문제점

1. **코드 재사용의 제약**: 상속을 통한 코드 재사용이 간편한 경우가 많지만, 상속을 인터페이스로만 제한하고 컴포지션을 사용하도록 강제하면, 일부 상황에서는 코드 재사용이 더 복잡해질 수 있습니다. 특정 기능을 재사용하기 위해 추가적인 래퍼(wrapper) 클래스나 더 많은 보일러플레이트 코드가 필요할 수 있습니다.

2. **설계의 복잡성 증가**: 컴포지션은 유연성을 높이고 결합도를 낮추는 장점이 있지만, 잘못 사용되었을 때 시스템의 전체적인 설계가 복잡해질 수 있습니다. 컴포넌트 간의 인터페이스를 정의하고, 상호 작용하는 방식을 설계하는 것이 상속을 사용하는 것보다 복잡하거나 어려울 수 있습니다.

3. **성능 문제**: 컴포지션과 인터페이스를 사용하는 설계는 때때로 상속 기반 설계에 비해 성능상의 손해를 볼 수 있습니다. 특히, 고성능을 요구하는 시스템에서는 인터페이스 호출이나 객체 구성으로 인한 오버헤드가 문제가 될 수 있습니다.

결론적으로, 상속 대신 컴포지션과 인터페이스를 사용하는 접근 방식은 프로그램의 유연성과 유지보수성을 크게 향상시킬 수 있지만, 설계의 복잡성 증가나undefined