[개발자가 반드시 정복해야 할 객체 지향과 디자인 패턴] 재사용: 상속보단 조립

·2022년 10월 26일
0
post-thumbnail

[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) {
				// bounds 객체에 처리를 위임함
				return **bounds.contains**(point.getX(), point.getY());
		}
}
  • 위임은 조립과 마찬가지로 위임할 객체를 필드로 연결
  • 객체를 새로 생성해서 요청 전달해도 됨

상속은 언제 사용하나?

  • 명확한 IS-A 관계에서 점진적으로 상위 클래스의 기능을 확장해 나갈 때 사용

0개의 댓글