1. 개요
•
상속과 합성은 객체지향 프로그래밍에서 가장 널리 사용되는 코드 재사용 기법이다.
•
상속 = 부모 클래스와 자식 클래스를 연결해 코드를 재사용
•
합성 = 전체를 표현하는 객체가 부분을 표현하는 객체를 포함해 코드를 재사용
•
상속과 합성은 재사용의 대상이 다르다.
◦
상속은 부모 클래스 안에 구현된 코드 자체를 재사용
◦
합성은 포함되는 객체의 퍼블릭 인터페이스를 재사용한다.
2. 상속을 합성으로 변경하기
•
상속을 남용했을 경우 마주할 수 있는 문제는 크게 3가지다.
2.1.불필요한 인터페이스 상속 문제
•
자식 클래스에게는 부적합한 부모 클래스의 오퍼레이션이 상속되기 때문에 자식 클래스 인스턴스의 상태가 불안정해지는 문제
•
클래스의 상속관계를 제거하고 상속 하고자 하는 부모 클래스를 자식 클래스의 인스턴스 변수로 포함시켜 해결한다.
2.2. 메서드 오버라이딩의 오작용 문제
•
자식 클래스가 부모 클래스의 메서드를 오버라이딩할 때 자식 클래스가 부모 클래스의 메서드 호출 방법에 영향을 받는 문제
•
메서드 오버라이딩이 아닌 인스턴스 변수에 포함시켜 퍼블릭 인터페이스를 통해서 기능을 확장시킨다.
2.3. 부모 클래스와 자식 클래스의 동시 수정 문제
•
부모 클래스와 자식 클래스 사이의 개념적인 결합으로 인해 부모 클래스를 변경할 때 자식 클래스도 함께 변경해야 하는 문제
public class PersonaIPIay1ist {
private Playlist playlist = new Playlist();
public void append(song song) {
playlist.append(song);
}
public void remove(Song song) {
playlist.getTracks() .remove(song);
playlist.getSingers().remove(song.getSinger());
}
}
Java
복사
•
해당 클래스는 상속이 아는 합성이지만, 여전히 기능 변경 시 함께 수정되어야한다.
•
그렇다고 하더라도 파급효과를 줄이기 위해 합성을 쓰는편이 더 좋다.
3. 상속으로 인한 조합의 폭발적인 증가
•
상속으로 인해 결합도가 높아지면 코드 수정에 필요한 작업의 양이 과도하게 늘어나는 경향이 있다.
•
일반적으로 작은 기능들을 조합해 더 큰 기능을 수행하는 객체를 만들어야 하는 경우
•
일반적으로 발생하는 두 문제점
◦
하나의 기능을 추가하거나 수정하기 위해 불필요하게 많은 수의 클래스를 추가하거나 수정해야 한다.
◦
단일 상속만 지원하는 언어에서는 상속으로 인해 오히려 중복 코드의 양이 늘어날 수 있다.
•
이처럼 상속의 남용으로 하나의 기능을 추가하기 위해 필요 이상으로 많은 수의 클래스를 추가해야 하는 경우를 가리켜 클래스 폭발(class explosion) 문제 또는 조합의 폭발(combinational explosion) 문제라고 부른다.
•
컴파일 타임에 결정된 자식/부모 클래스 사이의 관계는 변경될 수 없다.
◦
때문에 자식 클래스와 부모 클래스의 다양한 조합이 필요한 상황에서 유일한 해결 방법은 조합의 수만큼 새로운 클래스를 추가하는 것뿐이다.
•
해당 문제는 추가 뿐 아니라 수정에도 문제가 되는데 중복코드 수정이 누락될 경우 버그가 발생할 수 있다.
4. 합성 관계로 변경하기
•
상속 관계는 컴파일타임에 결정되고 고정되기 때문에 실행 도중 변경이 불가능하다.
◦
따라서 여러 기능을 조합해야 하는 설계에 상속을 이용하면 모든 조합 가능한 경우별로 클래스를 추가해야 한다.
•
합성은 컴파일타임 관계를 런타임으로 변경해 이 문제를 해결한다.
•
합성을 사용하면 컴파일 의존성에 속박되지 않고 다양한 방식의 런타임 의존성을 구성할 수 있다.
•
해당 합성 구조로 인해서 새로운 정책/부가 정책 추가가 편리해진다.
•
코드를 재사용하면서도 건정한 결합도를 유지하는 합성이 상속보다 더 좋은 방법이다.
5. 믹스인
•
상속을 사용하면 다른 클래스를 간편하게 재사용하고 점진적으로 확장할 수 있지만 부모/자식 클래스가 강하게 결합되어 수정과 확장이 취약해진다.
•
믹스인은 객체를 생성할 때 코드 일부를 클래스 안에 섞어 넣어 재사용하는 기법을 가르키는 용어다.
◦
합성 = 실행 시점에 객체를 조합하는 재사용 방법
◦
믹스인 = 컴파일 시점에 필요한 코드 조각을 조합하는 재사용 방법
•
믹스인 ≠ 상속
•
방법이 무엇이건 코드를 다른 코드 안에 유연하게 섞어 넣을 수 있다면 믹스인이라 부를 수 있다.