좀 방대한 질문이어서 제대로 답변드리기 힘들 것 같습니다.
대신 제가 전에 제 홈페이지 강좌에 관련된 내용을 올린 적이 있어서 그 내용을
올릴까 합니다.
대략 요약적으로 말씀 드리자면 본질적인 내용의 상속은 클래스를 이용하고
비본질적인 내용의 상속은 인터페이스를 이용합니다.
인터페이스는 데이터는 갖고 있지 않고 메소드 멤버들만 가지고 있기 때문에
다분히 기능 지향적입니다.
예를 들어, 자동차와 집은 서로 같은 클래스 라인에 묶일 만한 요소가 별로 없어
보입니다.
그렇지만 둘 다 구입시 은행에서 대출을 받을 수 있다는 약간 비본질적인
공통점이 있다면 이 기능만 인터페이스로 만들어서 상속하는 것입니다.
물론 C++에서처럼 다중 상속을 이용할 수 있습니다만,
다중 상속은 워낙 복잡한 데다가 다이아몬드 상속의 경우처럼 혼란을 초래하는
경우가 있기 때문에
실제로 별로 사용되지가 않습니다.
그렇지만 인터페이스는 개념적으로 깔끔하고 구현도 쉽기 때문에 많이 사용되고
있습니다.
그럼 다음의 글을 읽어보시기 바랍니다.
Sam
-------
Interface를 이용한 유연한 Polymorphism
지난 강좌에서 봤듯이 Polymorphism을 이용하면 프로그램이 아주 단순해질 수
있습니다.
그런데 이것을 좀더 확장해서 생각해 보겠습니다.
Animal들만이 Talk를 하는 것이 아니라 Animal이 아닌 것들도 Talk를 한다고
생각해 봅시다.
이럴 경우 다음의 메소드는 사용할 수가 없습니다.
void makeItTalk(Animal animal)
왜냐하면 파라미터로 Animal 타입만을 받아들이기 때문입니다.
그런데 뻐꾸기 시계도 Talk를 한다고 생각해 봅시다.
분명 뻐꾸기 시계는 Animal이 아닌데 Talk하는 기능은 갖고 있습니다.
이럴 경우 Animal과는 별도의 클래스 계층을 만들고 거기에 Talk를 넣어야
할까요?
이렇게 해도 문제는 여전히 남습니다.
다음의 메소드에 어떤 타입의 파라미터를 지정해 줘야 할까요?
void makeItTalk(???)
이처럼 같은 클래스 계층에 넣을 수는 없지만 공통적인 기능들은 interface에서
처리해 주는 것이 좋습니다.
예제 코드를 보겠습니다.
using System;
interface ITalkative
{
void Talk();
}
abstract class Animal
{
abstract public void Talk();
}
class Dog: Animal, ITalkative
{
override public void Talk()
{
Console.WriteLine("I'm a dog...");
}
}
class Cat: Animal, ITalkative
{
override public void Talk()
{
Console.WriteLine("I'm a cat...");
}
}
class Clock
{
}
class CuckooClock: Clock, ITalkative
{
public void Talk()
{
Console.WriteLine("I'm a cuckoo clock...");
}
}
class MainClass
{
static void makeItTalk(ITalkative talkative)
{
talkative.Talk();
}
static public void Main()
{
ITalkative dog = new Dog();
ITalkative cat = new Cat();
ITalkative cuckooclock = new CuckooClock();
makeItTalk(dog);
makeItTalk(cat);
makeItTalk(cuckooclock);
}
}
CuckooClock이라는 클래스는 Animal은 아니지만 ITalkative 라는 인터페이스를
구현함으로써
Dog나 Cat와 공통점을 갖게 된 것이고 이것들을 ITalkative라는 인터페이스로
묶을 수 있는 것입니다.
static void makeItTalk(ITalkative talkative) 메소드도 Dog나 Cat뿐 아니라
CuckooClock 타입의 파라미터도 받을 수 있게끔 수정되었습니다.
이처럼 인터페이스를 이용하여 같은 상속라인(Family)의 클래스들만이 아닌
공통적 기능을 하는 클래스들을 함께 묶어서 처리할 수 있는 것입니다.
인터페이스는 클래스와는 달리 메소드의 프로토타입만을 가질 수 있습니다.
필드나 메소드의 구현은 포함할 수 없습니다.
프로퍼티는 실질적으로는 메소드이므로 포함될 수 있습니다.
그리고 인터페이스를 구현하는 클래스에서는 인터페이스에 선언된 메소드를 모두
구현해야 합니다.
이처럼 일종의 구현에 대한 계약이 맺어져 있기 때문에 interface를 contract라고
합니다.
'알고리즘' 카테고리의 다른 글
리팩토링 - 과거와 대결하는 프로그래머의 무기 (1) | 2005.08.26 |
---|---|
static을 이해하자 (0) | 2005.06.23 |
하노이 타워 (0) | 2005.03.09 |
논리적인 문제 (0) | 2005.01.06 |
GDI 에 대한 설명 (0) | 2004.11.16 |