[1] 상속과 재사용
- 상속을 사용하면 쉽게 다른 클래스의 기능을 재사용하면서 추가 기능을 확장할 수 있음 ⇒ 상속은 기능을 재사용하는 매력적인 방법임
- 하지만, 상속은 유연함이라는 측면에서 치명적인 단점을 가짐.
상속을 통한 재사용의 단점
1. 상위 클래스 변경의 여려움
- 상속 계층에 따라 상위 클래스의 변경이 하위 클래스에 영향을 주기 때문에, 클래스의 계층도가 커질수록 상위 클래스의 변경이 어려워짐
2. 클래스의 불필요한 증가
- 유사한 기능을 확장하는 과정에서 클래스의 개수가 불필요하게 증가할 수 있음
3. 상속의 오용
- 수하 목록 관리 기능 구현을 위해 ArrayList를 상속받는 Container 클래스를 생성하고, 수하물을 싣는 메소드는 put 이라고 하자.
- 사용자가 ArrayList 클래스에 등록된 메서드인 add를 put과 혼동하여 사용한다면, 기능은 정상적으로 작동하지 않는다.
- 이와 같은 문제가 발생하는 이유?
- 컨테이너는 ArrayList와 IS-A 관계가 아니기 때문! (IS-A 관계: “컨테이너는 ArrayList이다.”)
- 같은 종류가 아닌 클래스의 구현을 재사용하기 위해 상속을 받게 되면, 잘못된 사용으로 인한 문제가 발생하게됨
[2] 조립을 이용한 재사용
- 객체 조립(composition): 여러 객체를 묶어 더 복잡한 기능을 제공하는 객체를 만들어내는 것
- 보통 필드에서 다른 객체를 참조하는 방식으로 구현
- 클래스 증식 문제가 사라짐
- 런타임에 조립 대상을 교체할 수 있다.
💡 상속보다는 객체 조립을 사용할 것
위임
- 위임(delegation): 내가 할 일을 다른 객체에게 넘긴다
- 보통 조립 방식을 이용해 위임 구현
public abstract class Figure {
private Bounds bounds = new Bounds();
...
private void changeSize() {
bounds.set(x,y,width,height);
}
private boolean contains(Point point) {
return **bounds.contains**(point.getX(), point.getY());
}
}
- 위임은 조립과 마찬가지로 위임할 객체를 필드로 연결
- 객체를 새로 생성해서 요청 전달해도 됨
상속은 언제 사용하나?
- 명확한 IS-A 관계에서 점진적으로 상위 클래스의 기능을 확장해 나갈 때 사용