새로은 클래스는 기존 클래스에 기반을 둔 클래스 상속을 사용하여 정의할 수 있다.
서브클래스(sub class)는 부모 클래스(parent class)를 상속하면 부모 클래스가 갖는 모든 데이터와 연산을 서브클래스가 갖게 된다.
일단 클래스와 타입의 차이를 이해해야 한다.
클래스도 객체가 수행할 수 있는 연산을 정의 하므로, 객체의 타입을 정의하는 것이기도 한다.
그래서 어떤 객체가 어떤 클래스의 인스턴스라고 말할 때, 그 객체는 그 클래스가 정의한 인터페이스를 지원한다는 뜻이기도 하다.
클래스 상속은 기본적으로 부모 클래스에서 정의한 구현을 재사용하여 응용프로그램의 기능성을 확장하려는 메커니즘이다.
이미 있는 것을 이용해서 새로운 객체를 빨리 정의해 보려는 것 위함으로, 기존의 클래스를 그대로 상속할 수 있다면 새로운 구현에 드는 비용은 공짜인 셈.
추상 클래스를 정의하고 인터페이스 개념으로 객체를 다룰 때 얻을 수 있는 점은,
객체지향 시스템에서 기능의 재사용을 위해 구사하는 가장 대표적인 기법은 클래스 상속, 그리고 객체 조합(object composition) 이다.
우리가 상속을 통해 얻고자 하는 점은,
하지만, 상속을 적절하게 사용하지 못하면 아래와 같은 단점이 있다.
캡슐화는 말그대로 캡슐에 넣듯 외부에서 감춘다는 의미이다.
캡슐화: 만일의 상황(타인이 외부에서 조작)에 대비해 외부에서 특정 속성이나 메서드를 사용할 수 없도록 숨겨놓는 것.
클래스 상속은 서브 클래싱, 즉 다른 부모 클래스에서 상속받아 한 클래스의 구현을 정의하는 것이다.
서브클래싱에 의한 재사용을 화이트박스 재사용(white-box reuse)이라고 합니다. 상속을 받으면 부모 클래스의 내부가 서브클래스에 공개되기 때문에 화이트박스인 셈이다.
화이트박스 재사용은 캡슐화가 깨짐으로써 하위 클래스가 상위 클래스에 강하게 결합, 의존하게 되고 강한 결합, 의존은 변화에 유연하게 대처하기 어려워진다.
조합은 이러한 클래스 상속에 대한 대안이다.
다른 객체를 여러개 붙여서 새로운 기능 혹은 객체를 구성함으로써,
객체의 내부는 공개되지 않고 인터페이스를 통해서만 재사용하고 이를 블랙박스 재사용(black-box reuse) 라고 한다.
이러한 단점을 해결하기 위해서 추상 클래스를 이용할 수도 있다.
추상 클래스에는 구현이 거의 없거나 전혀 없기때문에 이미 추상 클래스를 상속했다는 것은 구현이 아닌 인터페이스를 상속한 것이므로 구현 자체는 서브클래스가 정의한다.
구현이 변경되면 서브클래스만 변경하면 되고 상위 추상 클래스는 고려할 필요가 없습니다.
조합(Composition): 기존 클래스가 새로운 클래스의 구성요소로 쓰인다.
새로운 클래스를 만들고 private 필드로 기존 클래스의 인스턴스를 참조한다.
하지만 조합은 한 객체가 다른 객체에 대한 참조자를 얻는 방식으로 런타임에 동적으로 정의된다.
객체가 다른 객체의 인터페이스만 바라보게 하기 때문에 인터페이스 정의에 더 많은 주의를 기울여야 하지만 객체는 인터페이스에서만 접근하므로 캡슐화를 유지할 수 있다.
동일한 타입을 갖는다면 다른 객체로 런타임에 대체가 가능하므로 객체는 인터페이스에 맞춰 구현되므로 구현 사이의 종속성은 확실히 줄어든다.
상속보다 조합을 사용하는 이유는
각 클래스의 캡슐화를 유지할 수 있고,
각 클래스의 한 가지 작업에 집중할 수 있다.
클래스와 클래스 계층이 소규모로 유지되면서 유지 보수가 간결하다.
객체 합성으로 서계되면 클래스의 수는 적어지고 객체의 수는 좀 더 많아질 수 있지만, 시스템의 행동은 클래스에 정의된 정적인 내용보다는 런타임에 드러나는 객체 합성의 의한 상호 관련성에 따라 달라질 수 있다.
재사용을 위해서 새로운 구성요소를 생성할 필요 없이 필요한 기존의 구성요소를 조립해서 모든 새로운 기능을 얻어올 수 있다.
그러나 가능한 구성요소의 집합이 실제로 사용할 수 있을 만큼 충분하지 않기 때문에 기존 구성요소의 조합을 통한 재사용만으로 목적을 달성할 수 있는 경우는 적다.
상속에 의한 재사용은 기존 클래스들을 조합해서 새로운 구성요소를 쉽게 만들 수 있도록 해 준다.
그러므로 상속과 조합을 적절히 사용해야 완벽한 재사용이 가능하다.
캡슐화를 깨뜨리고, 상위 클래스에 의존하게 돼서 변화에 유연하지 못한 상속을 사용하기보다는 조합(Composition)을 사용하자.
하지만 조합(Composition)이 상속보다 무조건 좋다는 것은 아니다.
상속이 적절하게 사용되면 조합보다 강력하고, 개발하기도 편리하다.