[강좌] 예제로 알아보는 Class, Object, Abstract Class, Interface

현재 저는 HOONS 닷넷 에서 C# 스터디를 진행중이구요. 
조장을 맡고 있습니다.

그 때 발표한 Class와 Inheritance(상속)에 관한 내용을 정리해보겠습니다.

사실 클래스라 하면 다들 한번씩은 생각해보았을 용어이고, 나름대로의 정의를 다 내려보았을 것입니다.

그럼 클래스란 뭘까요?

클래스와 객체를 이해하기 쉽게 정의 내리기 위해서는 많은 설명들과 예시들이 동원되는데요.
저는 일단 이렇게 정의 내리겠습니다.

클래스란 “객체를 표현하기 위한 속성과 역할을 정의한 틀이다

그럼 여기서 객체는 무엇일까요?
그리고 객체와 클래스의 관계는 어떻게 될까요?

객체는 눈에 보이는 것이고 클래스는 그것을 나타내는 개념적인 것이라 할 수 있습니다.
다른 관점에서 보면 객체는 어떤 문제라고도 표현될 수도 있고, 클래스는 그 문제와 관계된 종합적 상황을 정의 한 것이라고도 설명할 수 있습니다.

그럼 클래스와 객체의 관계에 대해서 쉽게 알아보도록 하죠.


Class Object
그림1 그림2

흔히 많이 드는 예로 클래스는 붕어빵 틀에 비유하고, 객체는 붕어빵에 비유를 하죠.

붕어빵 틀붕어빵이라는 놈을 만들어 내기 위해 “뿡어빵은 이런 거야” 라는 점을 특징 지어주게 됩니다.
예를 들면 “뿡어빵은 눈이 있고 지느러미와 꼬리 모양을 가진 생선 모양이다, 그리고 내용물은 반죽과 팥이 들어가서,
잘 구어지면 색은 노릇한 색이다” 라구요.

뿡어빵 틀을 하나 구매했다고 생각해보죠.
그리고 그 붕어빵 틀을 통해 나온 붕어빵에는 구운 정도, 팥의 포함 정도에 따라 제각각의 객체로 만들어 봅니다.
다시 말해 클래스를 통해 생겨난 객체는 같을 수도 다를 수도 있습니다.

그럼 클래스와 객체에 대해서는 이해가 어느 정도 되셨을 겁니다.

그럼 Abstract Class(추상 클래스)는 무엇일까요?

그리고 추상클래스가 무엇인지를 아는 것 보다 중요한 추상 클래스를 사용하는 이유는 무엇일까요?

추상 클래스는 어떤 클래스를 만들어내기 위해서 기본 기능을 이미 포함하고 있는 클래스

라고 말할 수 있겠습니다.

여기서 “만들어내기 위해서” 라는 곳이 강조되었죠?
그렇습니다.

추상 클래스라는 놈은 상속을 받을 하위 클래스를 위해 존재하지, 추상 클래스 혼자로는 객체를 만들어 사용할 수 없습니다.

그럼 객체로도 만들어 쓸 수 없는 이 클래스는 왜 생겨났을까요?

추상 클래스는 본인을 상속받아 사용하는 하위 클래스를 지도하는 역할을 합니다.
”추상 클래스를 상속받는다” 함은
“나(추상 클래스)를 상속 받으면 이런 기본 기능은 사용할 수 있어” 라는 것과
“나를 상속 받으려면 이 정도 기능은 추가로 구현해야 사용할 수 있어” 라는 것을 알려줍니다.

그림3 
앞의 예를 좀더 이어 가보겠습니다.


앞에서 붕어빵 틀 클래스로 붕어빵 객체를 너무 많이 만들어 먹어서
이제는 붕어빵이 질렸습니다.

남은 반죽으로 할 수 있는 것을 찾아보다
우연히 인터넷에서 와플 사진을 발견했습니다.

붕어빵과 와플을 만드는 방법도 비슷합니다.

이제는 붕어빵 대신 와플이 먹고 싶습니다.

여기서 우리는 와플팬을 통째로 다시 사야할까요?
아니면 붕어빵틀을 녹여서 처음부터 와플팬을 만들어야할까요?

바로 이어서 추상클래스로 이 문제를 해결해보도록 하겠습니다.







그림4

모양 틀은 알아서 만들어 나머지는 내가 알아서 해줄게

그림5 그림6

위의 3가지 사진 중에 가장 위에 보이는 것이 2008년도 웰빙을 선도했던 샌드위치맨이라는 것입니다.
이 샌드위치 맨이라는 놈이 바로 추상 클래스입니다.

아까 보셨던 붕어빵 틀은 사실 탈부착이 가능했습니다.
와플을 굽기 위해선 붕어빵 틀을 빼고 와플 모양의 틀만 부착하면 됩니다.
이 샌드위치맨이라는 것이 와플 틀을 부착하면 와플 메이커가 되고, 붕어빵 틀을 부착하면 붕어빵 메이커가 되는 것입니다.

이제 추상 클래스를 상속받고 모양 틀만 새로이 구현하므로써 새로운 클래스를 쉽게 만들 수 있겠죠?

그런데 사실 샌드위치맨 자체는 이 틀이 없이는 아무것도 구울 수 없습니다.
대충 “이런 틀을 만들어라” 라고 가이드 라인을 제시하고
그 틀을 이용해 실제 와플 메이커, 붕어빵 메이커라는 클래스가 되기 전까지는 실제로 사용할 수 없다는 것이죠.
이것이 바로 추상클래스의 특징이기도 합니다.

그렇다면 샌드위치맨이라는 것을 왜 추상 클래스화 했을까요?

붕어빵과 와플을 굽는 방법 두 가지는
“굽는 시간”과 “온도”만 틀릴 뿐 방법은 동일합니다.
공통되는 기능, 예를 들면 스위치를 켜면 온도가 올라가 빵이 만들어진다. 이 정도의 기능은 추상클래스에서 구현되어 있습니다.
그리고 굽는 시간, 온도 등도 추상 클래스의 속성으로 가져도 되겠군요.

이렇게 쉽게 붕어빵과 와플을 구분해서 만들 수 있죠?
심지어 다른 모양 틀을 만들어 새로운 클래스를 만들 수도 있습니다.

이것이 바로 추상 클래스를 사용하는 이유입니다.

자. 이번은 인터페이스 입니다.

많이 들어보고 직접 사용도 해봤지만, 그닥 자세히 인터페이스가 무엇인지는 알지 못하는 사람들이 많습니다.
그럼 인터페이스는 뭘까요?

인터페이스는 “객체 자체 혹은 객체와 객체를 엮어주기 위한 기능과 속성들의 약속(표준)이다”라고 정의 내릴 수 있겠습니다.

여기서 중요한 것은 약속, 표준이라는 말입니다.

인터페이스는 한번 정해지면 쉽게 바꿀 수 없고, 한번 약속을 맺었으면 반드시 그 약속을 이행하여야 합니다.
이해를 돕기 위해 인터페이스를 사용한 예를 보겠습니다.

그림0

세상에는 참 다양한 마우스가 있습니다.
그러나 마우스라는 개체가 모양이 아무리 다양해도,
PC라는 객체와 통신을 하기 위해서는 표준으로 정한 인터페이스를 구현하여야 합니다.

USB 인터페이스, PS2 인터페이스, 블루투스 인터페이스 중에 선택을 해야겠지요?
경우에 따라서는 2가지, 3가지의 인터페이스를 모두 적용할 수도 있을 것입니다.

필요한 인터페이스를 정하고 그 인터페이스를 사용했다는 의미로 해당 잭을 달아놓거나 블루투스 마크를 그려놓아서
이 인터페이스를 사용하였습니다. 라고 표시를 해줍니다.
물론 해당 인터페이스가 실제로 구현되어야 함은 당연한 말이구요.

USB 마우스인 경우 USB 잭을 보고 USB 인터페이스를 구현했구나 하고 PC 본체의 USB 홈에 꽂아서 사용합니다.
이것이 바로 인터페이스의 개념입니다.

PC와의 통신이라는 기능을 위한 인터페이스를 정하고 그 인터페이스의 내용을 구현하는 것입니다.

이해를 좀더 돕기 위해 이번에는 코드로 살펴보겠습니다.

class MyDisposableClass : IDisposable
{
   public void Dispose()
   {
        //etc 
   }
}


간단히 IDisposable 인터페이스를 사용한다고 예를 들어봅시다.
MyDisposableClass는 IDisposable 인터페이스를 상속받았습니다.
그 의미는 Dispose라는 함수가 반드시 MyDisposableClass에 구현되어 있다고 약속을 하는 것입니다.
그리고 이 객체를 다 사용하고 나면 명시적으로 Dispose라는 메소드를 호출해 주어야 할 것 같은 느낌이 듭니다.
그래서 MyDisposableClass를 사용하는 사람은 객체 안의 리소스를 명시적으로 반환하기 위해
using 구문안에서 객체를 선언하여 쓰겠죠.
using 문이 끝날 때 자동으로 Dispose함수가 불릴 테구요.

이처럼 인터페이스를 구현한다면 그 인터페이스가 가진 기능, 특징을 유추할 수 있고, 그 기능을 사용할 수 있음을 확신할 수 있습니다.

이것이 바로 인터페이스를 사용하는 이유입니다.

인터페이스와 추상클래스에 대해서 개념이 제대로 잡히지 않으신 분들이
주로 인터페이스의 상속을 이상하게 사용하는 것을 종종 볼 수 있는데요.

추상 클래스도 상속이 가능하고 인터페이스도 상속이 가능합니다.
그렇다면 상속이라는 측면에서 볼 때

추상 클래스와 인터페이스의 차이점은 뭘까요?

클래스는 단 하나의 추상 클래스를 상속받을 수 있고, 인터페이스는 다중 상속이 가능하다라는 말을 흔히 씁니다.
C#에서는 왜 이렇게 설계가 되었을까요?

사실 추상 클래스와 인터페이스에서의 상속의 의미는 서로 약간 다릅니다.
추상 클래스의 상속, 보통 클래스의 상속은 여러분이 알고 있는 수직적인 개념의 상속입니다.

그러나 인터페이스의 상속은 수평적인 개념의 상속입니다.

볼 마우스, 광 마우스는 마우스라는 클래스에서 상속받은 하위 클래스이지만,
USB, PS2 인터페이스를 사용한다는 것은 해당 기능을 사용하고, 구현한다는 수평적인 의미이지
상, 하위를 가지는 수직적인 의미의 상속은 아닙니다.
그래서 USB도 되고 PS2도 되고 블루투스도 되는 마우스가 존재하는 것처럼
하나의 클래스가 여러 개의 인터페이스를 상속 받을 수 있는 것입니다.

그리고 인터페이스는 클래스와는 달리 구현되어 있는 메소드가 존재하질 않습니다.
왜냐하면 약속을 나타내는 일종의 껍데기일 뿐입니다.

가능한한 이해를 돕기 위해 추상적으로 예를 들어 설명을 해보았는데
잘 이해가 되셨는지 모르겠네요.
개념이 잘 잡히지 않는 분들은 댓글로 남겨주시면 성심 성의껏 답변해드리겠습니다.

chaoskcuf
프로그래밍/TIP& Study 2009/03/17 01:06

트랙백 주소 : http://chaoskcuf.com/trackback/192

  1. 클래스 tracked from Charlie Shin 2009/04/21 11:21  삭제

    ㅎㅎ 사진까지 잘 정리되어 있어서 트랙백 합니다.

댓글을 달아 주세요

  1. kwangho 2009/03/18 08:22  수정/삭제  댓글쓰기

    좋은 정보감사합니다. 잘 읽고갑니다. 그림으로 정성껏 설명해주셨네요

Powerd by Textcube, designed by criuce
rss