상속과 구성은 많이 들어봤을 법한 주제입니다. A is a B일 때 상속을 쓰라고 합니다. 예를 들자면, 개와 동물은 그러한 관계의 한 예입니다. 몇 레퍼런스를 더 찾아보던 중에, 이 질문글을 보게 되었습니다. 그리고 좋은 답변글들을 보면서, 정사각형과 직사각형, 그리고 타원과 원도 A is a B의 관계에 있다는 것을 알게 되었습니다. 그리고 이 문제와 리스코프 원칙과 관련이 있다는 것도 알게 되었습니다.

 


 아래 예제를 보겠습니다.

 

 정사각형은 직사각형을 상속합니다. square 생성자는 부모 rect의 생성자를 호출하는데, 넘기는 변수는 h, h입니다. 높이와 너비가 같기 때문입니다.

 

 

 rect 클래스입니다. 여기에는 getArea 메서드만 있습니다.

 

 

 이 프로그램의 출력 결과는 25입니다. 그런데, 사실 이것은 그리 중요한 부분이 아닙니다. 우리가 관심이 있는 부분은 딱 하나입니다. 정사각형은 직사각형이다. 즉, A is a B의 관계입니다. 표면적으로만 보아서는 그렇습니다.

 


 이제 직사각형에 setH와 setW 메서드가 추가되었다고 해 보겠습니다.

 

 

 이들은 높이, 너비 하나를 set 하는 메서드들입니다.

 

 

 문제는 정사각형은, 높이와 너비가 같아야 한다는 전제 조건이 깔려 있다는 것입니다. 즉, 정사각형 객체는 h와 w가 다른 상태가 존재하면 안 됩니다.

 

 

 문제는, setH나 setW는 각각 w 값에 상관 없이 h값을 바꿀 수 있고, h 값에 상관 없이 w 값을 바꿀 수 있는 메서드라는 겁니다. 정사각형은, w값에 상관 없이 h값을 마음대로 바꿀 수 없습니다. h값과 w값이 같아야 하기 때문에, h가 바뀌면 w값도 바뀌어야 하는 상황이 벌어집니다.

 

 

 이런 정사각형은 없습니다. 정리하면 정사각형은 직사각형은 맞지만, 직사각형의 특성 중에, 정사각형의 특성에 포함되지 않는 것이 있습니다. 이는 질문 글의 답변에서 나온 Square can do everything that Rectangle do. 에 위배가 됩니다. 정사각형을 가로로만 늘리거나, 세로로만 늘릴 수는 없기 때문입니다.

 

 


 그러면 이 두 관계는 어떻게 하면 좋을까요?

 

 아예 별개의 관계로 보면 어떨까요? 대신에, rect와 square는 모양, 도형이라는 공통적인 특징이 있습니다. 도형이라는 추상화된 것을 만들고, 그것을 square나 rect가 implements 하게 만들면 어떤가요?

 

 

  일단 요래 추상화를 시켜 봅시다. getArea는 shape에 있는 추상화 메소드입니다.

 

 

 그리고 square나 rect에서는 getArea라는 메서드만 구현하면 됩니다.

 

 

 요렇게요. 중요한 것은 정사각형은 직사각형을 상속받는 관계가 아니라는 겁니다. 단지, getArea라는 것을 구현했다는 공통점만 가지고 있습니다.