Skip to content

Latest commit

 

History

History
62 lines (43 loc) · 4.41 KB

아이템36_상속보다는_컴포지션을_사용하라.md

File metadata and controls

62 lines (43 loc) · 4.41 KB

상속보다는 컴포지션을 사용하라

  • 상속은 굉장히 강력한 기능으로, ‘is-a' 관계 의 객체 계층 구조를 만들기 위해 설계됨.

  • 단순하게 코드 추출 또는 재사용을 위해 상속을 하려고 한다면, 조금 더 신중하게 생각해야 하며,일반적으로 이러한 경우에는 상속보다 컴포지션을 사용하는 것이 좋음.

  • 상속의 단점

    • 상속은 하나의 클래스만을 대상으로 할 수 있습니다. 상속을 사용해서 행위를 추출하다 보면, 많은 함수를 갖는 거대한 BaseXXX 클래스를 만들게 되고, 굉장히 깊고 복잡한 계층 구조가 만들어집니다.
    • 상속은 클래스의 모든 것을 가져오게 됩니다. 따라서 불필요한 함수를 갖는 클래스가 만들어질 수 있습니다
    • 상속은 이해하기 어렵습니다.
  • 상속의 대안 컴포지션이란? -> 객체를 프로퍼티로 갖고, 함수를 호출하는 형태로 재사용하는 것을 의미.

image

  • 위 컴포지션의 예시를 보면 알 수 있듯이, 프로퍼티로 가지고 있는 객체를 활용하기 위해 open해야하는 메서드들을 적절하게 만들어줘야 하는 번거로움이 있음.

  • 다만, 코드를 읽는 측면에서는 더욱 가독성이 높으며 클래스 내부에서 객체를 재사용할 수 있는 장점이 있음.

  • 또한 2개 이상의 기능이 필요한 경우 상속은 다중이 안되지만 컴포지션은 생성 인자로 객체를 2개만 받으면 됨.

  • 그리고 상속은 굳이? 불필요한 데이터나 메서드까지 가져오게 되는 단점이 존재.

    • 개인적으로 그냥 상황에 맞는거 사용하면 된다고 생각함.

모든 것을 가져올 수 밖에 없는 상속

  • 상속은 슈퍼클래스의 메서드, 제약, 행위 동 모든것을 가져옴.
  • 따라서 상속은 객체의 계층 구조를 나타낼 때 굉장히 좋은 도구이지만 일부분을 재사용하기 위한 목적으로는 적합하지 않음
  • 일부분만 재사용하고 싶다면, 컴포지션을 활용하자.
  • 코틀린은 자바와 같이 다중 상속을 지원하지 않기에, 계층 구조를 표현해야 하는 경우에는 되도록 인터페이스를 활용하자.

캡슐화를 깨는 상속

  • 상속을 활용할때는 외부에서 이를 어떻게 활용하는지도 중요하지만, 내부적으로 이를 어떻게 활용하는지도 중요.

  • 라이브러리의 변경 상황에서도 상속보다는 컴포지션 형태가 대응하기에 유연.

  • 다만 이 경우에는 다형성이 사라지는 문제가 있지만, 코틀린에서는 위임패턴을 활용하면 됨.

  • 상속

image

  • 위임 패턴

image

  • 포워딩 메서드는 컴파일 시점에 만들어 짐.

오버라이딩 제한하기

  • 개발자가 상속용으로 설계되지 않은 클래스를 상속하지 못하게 하려면, final 을 사용하면 됨
  • 그런데 어떤 이유로 상속은 허용하지만, 메서드는 오버라이드하지 못하게 만들고 싶은 경우가 있을 수 있는데 이때는 open 키워드를 사용할수 있다.

정리

  • 컴포지션은 더 안전합니다. 다른 클래스의 내부적인 구현에 의존하지 않고, 외부에서 관찰되는 동작에만 의존하므로 안전.
  • 컴포지션은 더 유연. 상속은 한 클래스만을 대상으로 할 수 있지만, 컴포지션은 여러 클래스를 대상으로 할 수 있음.
  • 상속은 모든 것을 받지만, 컴포지션은 필요한 것만 받을 수 있음.
  • 컴포지션이 더 명시적
    • 슈퍼클래스의 메서드를 사용할때 리시버를 따로 지정하지 않아도 됨.
    • 이는 명시적이 아니며, 컴포지션의 경우에는 객체를 프로퍼티로 가지므로 명시적인 리시버를 사용하게 됨.
  • 컴포지션은 상속보다는 코드 작업이 더 들어가게 됨.
  • 상속은 다형성을 활용할 수 있음
  • OOP 관점에서 상속보다는 컴포지션이 나음.
  • 상속은 정확히 is-a 관계인 경우에만 적용하도록 하자.