소프트웨어에서 중복은 악이다. 이러한 중복을 제거하는 가장 잘 알려진 방법은 상속이다. 사람들은 상속을 단순히 중복을 제거하기 위해 무분별하게 사용한다. 이러한 상속의 사용이 정말 중복을 제거하여 유지보수하기 좋은 코드를 만들까? 이는 다시 한번 생각해볼 필요가 있다.
중복을 제거하기 위해 상속을 사용하는 경우 부모 클래스와 자식클래스는 강하게 결합된다. 부모의 공용 인터페이스를 상속받을 뿐 아니라 인스턴스 변수 등 다양한 부모의 내부 동작을 자식은 알고 있어야 하며 이는 부모와 자식을 강하게 결합하게 만든다. 강하게 결합된 클래스의 단점은 무엇인가? 하나의 클래스가 변경될 때 다른 클래스도 변경을 야기한다. 중복을 제거하기 위해서 상속을 사용하였는데 상속에서 다시 중복의 문제점이 발생하는 것이다.
뿐만 아니라 부모 클래스의 특정부분을 오버라이딩 하는 것도 유의하여야한다. 부모 클래스가 명확하게 어떠한 형태로 동작하는지에 대해 알지 못하고 부모클래스를 사용하거나 오버라이딩하는 경우 예상치 못한 결과가 도래할 수 도 있다.
그렇다면 자식클래스는 부모클래스의 내부 구현에 대해 깊게 이해하고 이를 문서화하여 작업하는 방식이 바람직한 방식으로 떠오를텐데 말만 들어도 무엇인가 이상하지 않은가? 이를 해결하기 위해서는 추상화에 의존해야한다. 아래에서 알아보겠다.
추상화에 의존한다는 말은 자식클래스가 부모클래스의 구현에 의존하는 것이 아니라 추상화에 의존하도록 변경해야 한다. 이를 위한 순서는 아래와 같다.
이렇게 하는 경우 최상위 추상 클래스에서는 부모와 자식이 공통적으로 담고 있는 부분을 정의하기 때문에 그 부분이 수정되면 최상위 추상 클래스만 수정하면 된다. 반대로 부모와 자식은 각기다른 형태로 추상 메서드를 정의하고 있기 때문에 각자의 역할이 변경되면 각자 수정하면 된다. 즉 하나의 변경사항에 대해서만 변경이 이루어지며 결합도가 낮아진다는 의미이다.
하지만 이런 경우는 어떨까? 부모와 자식 모두에게 적용되는 추가적인 기능이 존재할 때 이를 최상위 추상 클래스가 인스턴스로 갖게 되는 경우는 모든 객체가 수정을 해야한다. 즉 상속은 어떠한 형태로든 자식과 부모를 결합시킨다. 이를 완전히 제거할 수 있는 방법은 존재하지 않는다.
개인적인 결론으로는 상위 개념으로서 부모클래스나 인터페이스는 최대한 변경의 가능성이 적다는 확신을 가지고 만들어야한다. 상위 개념에서의 변화는 필연적으로 하위 객체들에게 영향을 미친다. 따라서 추상화를 할 때 상위 개념에 대해 명확하게 정의하는 것이 바람직하다.
상속과 같이 기존 코드와 다른 부분만을 추가함으로써 애플리케이션의 기능을 확장하는 방법을 차이에 의한 프로그래밍이라고 부른다. 객체지향 세계에서 중복 코드를 제거하고 코드를 재사용할 수 있는 가장 유명한 방법은 상속이다. 상속은 분명히 중요한 개념이고 효용을 가지고 있지만 단순히 중복의 제거의 목적으로 사용하는 것은 바람직하지 않다. 즉 잘 추상화된 상위개념아래에 차이에 의해 각 계층의 기능을 정의하였을 때 하나의 타입으로 다양한 기능을 제공하는 추상화된 형태로 사용될 수 있다.