[강좌 : 객체지향 - 6] 상속성
2009.10.01 12:31
김성용(topmentor)
http://cafe.naver.com/gisdev/611  
6. 상속성
 
 
오랜만에 다시 이어갑니다. 지금도 중요한 일을 하고 있어야 하는 데 귀차니즘 때문에 그것은 미루고 이것에 손을 대고 있네요. ^^<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /><?xml:namespace prefix = o />
 
이번 시간은 상속입니다. 상속은 객체지향의 꽃이라고 할 수 있습니다. 상속이 없다면 기존의 절차지향과 다를 게 없습니다. 절차지향에도 기능이나 속성을 추상화할 방법은 존재했기 때문입니다. 기능은 함수를 통해 속성은 구조체와 같은 사용자 정의형을 통해 구현을 할 수 있었죠. 상속이 있기에 객체지향과 절차지향은 중대한 문법적 차별성을 갖게 된 겁니다. 따라서 객체지향에서는 이 상속을 이해하고 활용해야 객체지향의 묘미를 살리는 셈이 됩니다.
 
 
   가. 상속의 개념
     : 상속의 기본 개념은 상위개념의 특징을 하위개념이 물려 받는 것이라 했습니다. ‘남학생’이라는 개념은 ‘학생’이라는 상위개념의 속성을 물려 받고 있습니다. 이런 특징을 프로그래밍적으로 어떻게 지원하는 가 하면 하나의 클래스가 가지고 있는 특징(데이터와 함수)들을 그대로 다른 클래스가 물려 받도록 문법화 하였습니다. 즉, 상속이라는 관계표시만 해 두면 별다른 조치없이 클래스의 기능과 속성을 그대로 가져오게 된다는 것입니다. 이는 기존 클래스에서 새로운 기능이나 특성을 부가하는 것만으로도 새로운 클래스를 정의할 수 있게 하기 위해서 입니다.
 
좀 더 프로그래밍적 측면으로 접근해 보면 ‘상속한다’의 의미는 클래스의 멤버를 다시 정의하지 않더라도 다른 클래스의 멤버변수나 함수들을 자신의 것처럼 쓸 수 있는 것을 말하는 것입니다.
 
오호!! 오늘도 저쪽에서 질문을 날리는 군요.
“편리한 것 같기는 한데, 요즘 에디터는 Copy & Paste가 쉬워서 기존에 만들어둔 코드를 그대로 복사해서 붙이면 되는데 굳이 상속을 쓸 필요가 있나요?”
 
대단한 지적입니다. 맞습니다. 복사해서 붙이기 하면 간단히 해결될 수 있습니다. 그럼 이런 상황을 생각해 봅시다. 화면에 원을 출력하는 기능을 확장해서 동심원을 출력하는 모듈을 만든다고 생각해 봅시다. 만약 복사를 해서 원을 출력하는 로직을 가져다 동심원 출력 모듈을 완성했다면 원을 출력하는 기능을 만든 사람이 그것을 업데이트 했을 때 동심원에 적용한 원 출력 로직은 업데이트가 안 된 상태로 남아있게 됩니다. 기능을 상속받았다면 업데이트 된 로직이 그대로 적용되었을 것입니다. 유지보수의 측면에서 상속이 복사&붙이기 보다 훨씬 일관성이 있고 안전하다고 할 수 있습니다.
 
“그런 경우 복사해서 붙이지 않고 함수를 호출하는 식으로 되면 안 되나요?”
 
이런 경우 원래 모듈의 안정성을 기할 수 있을 겁니다. 그런데 자료구조나 속성은 어떻게 물려줄 까요? 상속은 데이터이든 로직이든 안전하게 하위 클래스로 물려주고 자신의 색깔도 잃지 않게 하는 장점이 있습니다.
 
이런 측면도 있습니다. A라는 사람이 Car라는 클래스를 구현하였습니다. B라는 사람이 SuperCar라는 클래스를 만들려고 합니다. 그런데 Car의 기능과 속성을 이용하면 쉽게 구현할 수 있을 것 같습니다. Car 클래스는 A의 통제하에 있는 것이라 섣불리 B가 Car를 직접 수정할 수는 없습니다. Car는 그대로 두고 자신은 SuperCar만 손댈 수 있도록 하되 Car의 속성과 기능을 가져와야 합니다. 상속은 이런 상황에서 쓸 수 있는 좋은 방법입니다. Car의 속성과 기능을 물려 받되 마음에 들지 않는 것은 오버로딩이나 오바라이딩을 통해서 재구현할 수 있기 때문입니다. 빌려쓰는 모듈을 건들지 않고 원하는 모듈의 기능을 완성한다. 좋지 않습니까?
 
 
 
   나. 상속시 객체 구조
     : 상속을 받은 하위 클래스로 만든 객체의 구조를 이해하는 것은 상속관련 문법을 이해하는 데 매우 중요한 의미를 갖습니다. 일단 하위 클래스 객체에 대한 대원칙을 말씀드리겠습니다.
 
 원칙적으로 상속을 하면 모든 멤버를 하위로 가져온다. 단, 사용할 수 있느냐 없느냐로 상속이 된다 안 된다를 판단한다.
 
이것을 그림으로 설명드리겠습니다.
 
<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" /><?xml:namespace prefix = v />
 
 
Car를 상속 받은 SuperCar 클래스를 가지고 인스턴스를 생성하면 위 그림과 같이 SuperCar 객체 내에 Car 객체를 포함하는 형태가 됩니다. 상속을 한다면 마치 기능과 속성단위로 하나씩 가져오는 것 같지만 실제로는 그렇지 않다는 것입니다. 상위객체를 통체로 안고 있는 것입니다. 이를 통해서 확인할 수 있는 사실 하나… 상속을 받을 때에는 필요한 멤버만 선택적으로 가져올 수는 없다는 것입니다. 도움이 되든 안 되든 모두 가져와야 하는 구조입니다.
 
이쯤에서 이런 질문을 하실 겁니다.
“접근지정자를 쓰면 필요한 것만 상속한다고 하던데요? 즉, private로 지정되는 것은 상속이 안 된다고 하던데…”
 
많은 객체지향 책에서 그렇게 설명하고 있습니다. 일부는 맞는 이야기입니다. 그런데 이 부분은 정확히 이해하셔야 합니다. 접근지정자는 접근을 제한하는 용도이지 상속을 제한하는 제한자가 아닙니다. 상속을 하면 모든 멤버를 가져오는 데 접근지정자에 의해 하위 클래스 쪽에서 접근하는 것을 차단하는 것입니다. 이런 식으로 해서 private멤버를 쓸 수 없게 되니 ‘상속이 안 된다’라고 표현을 합니다만 사실 정확한 표현은 아닙니다. 메모리상에서는 private 멤버도 엄연히 allocation되고 있습니다. 단지 쓰지 못할 뿐이죠.
 
부가적으로 설명하자면 private 멤버는 하위 클래스에서 접근이 차단됩니다. protected나 public으로 지정되어야 하위 클래스서 접근이 가능합니다.
 
그리고 C++에서는 private 상속, protected 상속, public 상속을 구분하도록 문법이 제공되지만 거의 99% public 상속을 하고 있기 때문에 거의 의미가 없다고 보시면 됩니다. 따라서 Java나 C# 같이 나중에 탄생한 객체지향 언어의 경우 상속방식을 접근제한자로 구분하는 문법이 없습니다.
 
자~ 정리해 보겠습니다.
상속의 목적은 새로운 클래스를 정의하는 데 기존의 클래스를 확장하여 정의하고 싶을 때 사용된다. 그리고 하위 클래스의 객체는 상위 클래스의 객체를 포함하는 형태를 취하며 접근지정자에 사용이 제한될 뿐이다.
 
다음 시간에는 다형성을 해야 되는 데 상속에 대해 한가지 더 이야기를 할 게 있어 그것을 다루려고합니다. 사실 객체지향이 제시하는 상속은 2가지가 있습니다. 오늘 알아본 것은 구현상속이라는 것입니다. 새로운 클래스 구현을 목적으로 하는 상속을 말합니다. 상속을 하면 상위 클래스의 기능과 속성을 물려받는다는 특징을 이용하는 것이죠.
 
그런데 한가지가 더 있습니다. Type 상속이라는 것이 있습니다. 이것은 클래스가 갖는 형태만 상속을 하는 것입니다. “‘형’만 상속을 한다.”는 것에 대해 감이 잘 안 오실 겁니다. 주는 것 없이 그저 유형만 가져온다는 게 어떤 의미를 지니고 왜 필요한지도 모르실 겁니다. 하지만 이것을 이해해야 다형성의 고비를 넘어가실 수 있습니다. 다음 시간에는 이 type 상속에 대해 알아 볼 겁니다.
 
C++에서는 엄밀히 구분하지 않지만 Java나 C#등에서는 이 두 가지 상속을 구분하는 문법을 제공하고 있습니다.
Posted by windship