객체지향 프로그래밍에서 서로 연관된 객체들의 관계를 표현할 때 상속, 위임, 합성으로 표현하며
가장 많이 사용되는 코드 재사용 기법.
각각의 장단점이 존재하며 사용해야 하는 상황이 다르기 때문에 적절한 곳에 사용하는 것이 중요하다!
상속
📍상속은 부모가 자식에게 물려주는 행위이며 객체지향 프로그램에서 부모클래스의 필드와 메서드를 자식클래스에서 사용가능하다.
- is a 관계(Taxi는 Car다)로 extends 키워드를 사용한다.
- 일반적인 클래스가 이미 구현되어 있고 좀 더 구체적으로 클래스를 구현하기위해 사용되는 기법!
- 자식클래스에 메소드를 정의하지 않아도 되지만 부모와 강한 결합도를 가지게 됨으로 변화에 대응하기가 어렵다.
- 정적인 관계로 컴파일 시간에 모든 관계가 결정되고 코드를 실행하는 중 변경불가
- 상속은 클래스간의 관계를 한눈에 파악하고 코드를 재사용할 수 있는 간단한 방법
- 변화가 자주 일어나는 상황에는 상속보다 위임
합성(Composition)
📍합성은 기존 클래스를 상속을 통한 확장대신, 필드로 클래스의 인스턴스를 참조하게 만드는 설계
- 서로 관련없는 클래스의 관계에서 클래스가 다른 클래스의 기능을 사용하여 구현해야 한다면 합성 방식 사용
- 런 타임에 두객체 사이의 의존성 해결
- Student클래스가 Subject의 기능이 필요할 때 따로 클래스 인스턴스 변수에 저장 후 사용한다.(포워딩)
위임
- 합성 (Composition)과 Forwarding을 합쳐 Delegation이라고 쓰인다.
- 어떤 일을 책임 지워 맡기는 것이며 어떤 기능을 자신이 처리하지 않고 다른 객체에 위임시켜 일 처리를 하도록 하는 것
- 자바에서는 쉽게 사용하도록 지원하지 않고 kotlin에서는 by라는 키워드를 통해 해결할 수 있다고 한다..!
- Driver에게 Passenger가 구현한 Car의 메서드를 위임함으로 Driver가 TaxDriver가 가진 drive를 호출할 수 있다.
🔍 상속의 단점으로 결합도가 높아지거나 불필요한 기능을 상속, 부모와 자식 동시에 수정하는 문제등으로 현업에서는 많이 사용하지 않는다고 한다.
그에 비해 합성은 결합도가 낮고 상속은 클래스 사이가 정적관계이지만 합성은 동적관계이기 때문에
컴파일 시 코드 작성 시점에 결정한 상속관계는 변경이 불가하지만, 합성은 실행시점에서 동적으로 변경이 가능하기 때문에
합성을 사용하고 인터페이스를 사용하면 런타임시에 외부에서 필요시 교체하면 사용할 수 있어서 유연한 설계가 가능하다고 한다!
합성을 이용하여 상위클래스에 의존하지 않고 유연하게 사용할 수 있지만
구현해 보면서 느낀 점은 클래스가 많아질수록 합성클래스의 관계는 파악하기 어려울 것 같다는 생각이 들었다..!