본문 바로가기

## 아이폰 ##

" object-c " Object Messaging


Chapter 2. Object Messaging

Object messaging은 쉽게 말하자면 한 객체의 멤버 함수인 method를 호출하는 것입니다.

보통 Objective-C 에서는 해당 객체에 메시지를 보낸다라고 표현을 합니다. C++에서는 멤버함수를 호출한다라는 표현을 쓰고 있습니다.

바로 이 표현이 Objective-C 의 OOP 스타일과 C++의 OOP 스타일의 주요 차이점이 되지 않나 싶습니다.

물론 이외에도 몇몇 다른점이 있지만 OOP 구성을 하는 전체적인 그림의 차이는 바로 이 표현에서 보입니다. Apple의 Objective-C 문서를 보면, 그리고 SmallTalk이나 기타 Objective-C 문서를 보면, 객체를 원으로 표현하고, 그 객체에 메시지를 보내는 것과 같은, 객체의 네트워크로 프로그램을 표현하는 것을 많이 보실 수 있을 겁니다. 바로 이런 표현을 도식화하면 그렇게 됩니다.
이런 것을 생각하면서 접근을 하게 되면 Objective-C 스타일의 OOP에 좀더 빨리 익숙해질 수 있을 것이라고 생각합니다.

2.1 메시지 호출법

한 객체에 메시지를 보내는 법, 다시 말하자면 그 객체의 method를 호출하는 법은 다음과 같습니다.

[객체 method]

즉 이것은 C++스타일의class.member_function 혹은 class->member_function과 같습니다.

하지만 이것을 좀더 Objective-C 다운 표현으로 바꿔 보자면 다음과 같습니다.

[receiver message]

즉 호출대상이 되는 객체는 보내는 메시지를 받는 것이 되므로 receiver라 하고, 그 객체의 method를 메시지로 보내기 때문에 호출되는 메소드에 대해서는 message라고 표현을 합니다. 생각의 차이지만 이렇게 표현이 달라진다는 점이 재미납니다. 이제부터는 Objective-C 스타일로 모든 표현을 해 나가겠습니다.

여기서 또하나 재미난 점은 메시지의 receiver의 앞 과 message의 뒤에 [,]의 괄호로 둘러 쌓아 놓은 것입니다. 이런 스타일은 참 낯설기 그지 없어서, 많은 사람들이 Objective-C가 이상하다라고 할때 종종 언급하는 것입니다. 물론 처음에 볼때는 참 낯설어 보입니다. 하지만 하지만 익숙해지면 나름대로 깔끔해 보이고, 아 객체에 대해서 뭔가를 하는구나가 눈에 확 띕니다.

물론 부정적인 면도 없지는 않습니다. C++스타일로 포인터냐 아니냐에 따라 ->나 .를 쓰게 되면, 좌에서 우로 쓰면서 계속 연달아 쓸 수 있습니다. 쓰면서.. 아 이건 객체지 하면서 쓸 수 있단 뜻입니다.

하지만 Objective-C 는 receiver를 쓰기 전에, 아 객체에 메시지를 보내야지란 생각을 먼저해야 하고 그 다음에 [을 쓰고서 시작해야합니다. 그러지 않으면 일단 뒤에까지 죽 썼는데, 아차! 하면서 앞으로 다시 커서를 옮기고 괄호를 써야겠죠. 이 표현은 nesting될 수 있는데 그 경우엔 더 합니다.


즉 다음을 봅시다.

[[[A child] child] child]

여기서 child가 객체들이 내부적으로 가지고 있는 어떤 객체를 반환한다고 합시다. 이럴 경우엔 A앞에 괄호가 세개나 들어가므로 좀 writability가 떨어지기는 합니다.
맨처음 Objective-C를 배울때, 필자같은 경우, 이런 표현때문에 좀 고생을 했고, 여전히 C/C++ 프로그래밍을 하는 입장이다보니 좀 불편하기까지 합니다만, 그래도 Objective-C를 쓸때는 어쩔 수 없습니다.

개인적으로 Xcode의 editor가 이런 것을 자동으로 괄호를 쳐 주었으면 편하겠다 싶습니다.

이제 method가 인자를 가질때를 살펴봅시다.

[myRect setWidth:10.0 height:15.0]

즉 myRect라는 어떤 객체에 그 사각형의 폭과 높이를 10.0과 15.0으로 세팅을 하는 것입니다. 이런 표현도 낯섭니다. setWidth까지는 함수의 이름이겠거니하고 별 부담이 없이 받아들여지는데 height 부분은 낯섭니다. 이게 함수 이름의 부분인지 아니면 뭔지..
Objective-C는 인자에 이름을 붙일 수 있습니다. 위의 method를 정의 한다면 이렇게 될 것입니다.

- (void) setWidth: (float ) width height: (float) height

주의깊게 이 proto type을 살펴 봅시다.
제일 앞의 는 이 methodinstance method라는 것을 의미합니다.
즉 C++의 멤버함수와 같습니다.

그리고는 이 method의 반환값에 대한 형태가 괄호를 이용해서 (void)라고 되어 있습니다.
그 뒤에는 method의 이름인 setWidth가 나옵니다.

이제부터는 이 method의 인자를 쓰게 되는데, 우선 :를 써서 인자를 구별합니다.
그리고 각 인자의 형은 괄호를 이용해서 표현을 합니다.

즉 (float) width는 이 메소드의 첫번째 인자는 width라는 변수를 통해서 전달되며 그 형은 float입니다. 그리고 두번째 인자를 쓰는데, 여기서 특이한 점이 인자에 이름을 붙인다는 것입니다. 즉 height: 부분이 두번째 인자의 이름입니다. 그리고 그 다음에 두번째 인자를 씁니다.

불편하십니까? 무척 이상하게 보일겁니다. C/C++에 익숙해져 있다면, 어떤게 인자이고 어떤게 이름인지 눈에 잘 안띌 겁니다. 왜냐하면 C/C++은 괄호안에 각 인자를 컴마를 이용해서 넣게 되어 있기 때문입니다. 즉 괄호 안의 것들은 죄다 인자인데, Objective-C 는 어디서부터가 인자인지 눈에 잘 안들어옵니다.

하지만 이것은 익숙해지기 나름입니다. 이 Objective-C 스타일에 익숙해지시면, 나름대로 깔끔해 보입니다. 이런 표현은 나름대로 장점을 가집니다.

또한 한가지 이상한 점이 있습니다. 바로 method를 정의하는 앞에 –가 붙어 있는 것입니다.

이것은 다음과 같습니다.

- Instance method
+ Class method


+ 를 붙이면 C++의 클래스에서 static으로 선언한 것과 같은 효과를 볼 수가 있습니다.

2.2 Polymorphism (다형성)

Objective-C 도 OOP 언어인만큼 Polymorphism과 뗄래야 뗄 수 없는 관계에 있습니다.

하지만 지원하는 polymorphism은 C++의 그것과는 사뭇 다릅니다. 일단 이곳에서는 메시지 전달에 대한 것을 다루는 만큼 polymorphism도 C++과는 다르게 “메시지 전달”의 관점에서 살펴봅시다. 그리고 나서 일반적인 polymorphism에 대해서 알아봅시다.

C++과 마찬가지로 Objective-C 에서는 일단 객체가 다르다면 그들 사이에 같은 메소드를 가질 수 있습니다.

물론 인자가 완전히 동일할 수도 있고 다를 수도 있습니다. 이런 형태도 Objective-C 에서는 polymorphism에 해당합니다. 왜 그런가하면 “메시지 전달”이라는 점을 생각해 보면 알 수 있습니다.

이를테면 여러분의 코드가 display란 메시지를 Rectangle이란 객체와 Cube라는 객체에 보낸다고 합시다. 비록 두 객체가 다 display란 메소드를 가지고 있다고 해도, 하는 일은 아마도 다를겁니다. 하지만 보내는 측에서는 id두 객체를 가르킬수가 있으며, 아무런 문제없이 display란 메시지를 다 보낼 수 있습니다.

즉 다시 말하자면 다른 객체가 같은 메시지에 대해서 반응하므로 이것도 polymorphism에 해당합니다.

보통 C++에서 polymorphism이라고 하면 더 엄밀하게는 parametric polymorphism을 이야기 합니다. 즉 멤버 함수 이름은 같지만 그 인자는 다른 그런 경우입니다. 이런 것은 Objective-C 도 지원을 합니다. 또한 Objective-C는 C++처럼 parent 클래스 혹은 super class의 method도 overriding할 수 있습니다.

하지만 Objective-C 는 연산자 오버로딩 (operator overloading)은 지원하지 못합니다.

이것은 ad-hoc polymorphism이라고도 하는데, 이것을 잘 이용하면 덧셈 부호를 행렬의 덧셈에 사용한다던가 하는 식으로 상당히 깔끔하게 보이고 편한 코딩을 할 수가 있습니다. 아쉽게도 Objective-C 는 연산자 오버로딩은 지원하지 못합니다.

2.3 Dynamic Binding 혹은 Late Binding

이렇게 Objective-C에서 어떤 객체에 메시지를 보낼 수 있게 되는데, 객체와 해당 메시지는 언제 엮여지게 될까요?

그것은 runtime 시에 엮어집니다.

보통 Objective-C 프로그래밍을 하면 객체id의 형태로 받고 그것에 대해서 메시지를 보내기 때문에, compile 시에는 그 객체의 형태가 구체적으로 뭐가 되는지 알 수 없습니다. 그러므로 runtime 시에 하게 됩니다.

물론 이런 동적 바인딩 ( dynamic binding )은 장점도 있고 단점도 있습니다. 장점으로는 대단히 유연하다는 것입니다.

예를 들자면 여러가지 형태를 담는 리스트나 큐를 만들기가 쉽습니다.

하지만 단점도 있습니다. 우선 컴파일 시에 에러 메시지가 뜨지 않습니다. 그러므로 잘못 만들면 런타임 시에 찾기 힘든 에러가 발생할 수도 있습니다.

그 다음 문제로는 성능의 문제가 있겠습니다. 적어도 static binding을 하게 되면 컴파일시에 어지간한 잔 작업은 미리 해 놓기 때문에 런타임시에는 말그래도 주로 수행하는데만 CPU 타임을 쓰게 되지만, 동적 바인딩을 하면 그렇지 않습니다.

물론 Objective-C는 여러분의 선택에 따라 동적 바인딩과 정적 바인딩을 할 수있게 해줍니다. 이것은 뒤의 Chapter 7. Enabling Static Behaviour를 참고 하시기 바랍니다.

'## 아이폰 ##' 카테고리의 다른 글

" object-c " Classess  (0) 2010.10.21
" object-c " 객체  (0) 2010.10.21
" object-c " Language  (0) 2010.10.21
모바일웹 MP4.... 에혀... 이거  (0) 2010.08.13