정적 언어(C / C ++)와의 차이
- C / C++은 주로 "컴파일러"에 의존하는 정적인 언어라면, Objective-C는 "런타임"에 의존하는 동적인 언어이다.
- 동적인 언어의 특징은 Dynamic typing, Dynamic binding, Dynamic loading을 지원한다는 것이다.
1) Dynamic typing : 코드에서 다루는 오브젝트의 type이 무엇인지 실행 도중에 결정됨.
2) Dynamic binding : 코드상의 구문 statement가 어떤 method를 동작시킬 것인지 실행 도중에 결정됨
3) Dynamic loading : 실행 도중에 동적으로 실행될 모듈을 메모리에 loading할 수 있음.
*물론, C / C++ 도 Dynamic loading을 지원하며 특히 Dynamic binding은 다형성을 지원하는 객체지향 언어라면 반드시 필요로 하는 기능이기 때문에 C++에서도 핵심적인 부분이다. 하지만 이러한 기능들을 사용하는 메커니즘이나 방법이 objective-c가 훨씬 더 유연하게 사용한다는 것이다.
동적 바인딩?
- 정적 바인딩은 컴파일러 혹은 링커가 프로그램 실행전에 프로그래머가 작성한 method call(또는 message sending)에 대해 실행될 함수를 미리 연결시켜 놓는것이다.
- 동적 바인딩은 실행할 method call에 대한 함수를 프로그램 실행 도중 Runtime이 동적으로 결정한다는 것이다.
Objective-C의 Object 구조
- isa 포인터와 클래스 Object
: Objective-C의 모든 "인스턴스 Object"들은 isa라는 멤버 변수를 가지고 있다. isa의 타입은 Class타입인데 이것은 Objective-C의 "클래스 Object"를 가리키는 포인터이다. 그리고 id는 "인스턴스 Object"를 가리키는 포인터이다.
typedef struct objc_class* Class
typedef struct objc_object
{
Class isa;
} *id;
Objective-C에서는 클래스의 인스턴스 뿐 아니라 클래스 자체도 하나의 Object로서 존재한다.
인스턴스 Object가 만들어지는 과정을 보면, 클래스 Object의 alloc메서드가 호출되면 인스턴스 Object에 대한 메모리를 할당하고 자신(클래스 Object)을 참조하고 있는 isa포인터를 멤버변수로 세팅한다.
Dispatch table과 슈퍼 클래스
클래스 Object는 자신의 클래스가 정의하는 모든 method(인스턴스 method, 클래스 method)의 정보를 가지고 있다. 이를 Dispatch table이라 한다. 그리고 클래스 Object는 슈퍼클래스에 대한 포인터 isa를 멤버변수로 가진다.
Runtime은 인스턴스 Object가 메세지를 받으면 인스턴스 Object의 멤버변수 isa를 참조하여 자신의 클래스 Object를 찾는다. 그리고 클래스 Object의 Dispatch table을 참조해서 해당 메세지에 연결된 method 구조체를 참조해서 실제 함수를 실행한다.(method 구조체와 실제 함수 실행에 대한 부분은 추후 설명하겠다.) 만약 메세지에 해당하는 method 구조체를 찾지 못했을 경우 슈퍼클래스 Object를 가리키는 isa를 통해 슈퍼클래스의 Dispatch_table을 검색해서 매칭되는 method 구조체를 찾는다. 계속 적절한 method 구조체를 찾지 못하면 이 과정이 루트클래스까지 반복된다.
루트 클래스와 메타 클래스
- Cocoa 프로그래밍 환경에서 루트 클래스는 항상 NSObject 또는 NSProxy이다.(대부분 NSObject)
- 클래스 Object도 isa포인트를 가지고 있다. isa포인트는 항상 자신을 생성한 클래스 Object를 가리킨다. 클래스 Object를 생성하는 클래스는 메타 클래스라고 불리는데 이것에 대한 정보는 아직 신경쓰지 않아도 된다.(추후 설명하겠음.)
Selector(SEL), Method, 구현(IMP)의 정체
- Selector는 Method의 이름이라고 생각하면 된다. Method는 Selector와 실제 구현(IMP)을 연결시켜주는 구조체이다.
typedef struct objc_method
{
SEL method_name; //SEL은 보통 문자열의 포인터
char *method_types; //인수의 개수와 타입, 반환값에 따라 정해지는 메서드 타입이다.
IMP method_imp; //함수 포인터
}
- 위 그림에서 보다시피 메세지와 함수는 분리되어 있고 이를 Method 구조체가 연결하는 구조이다.
- 클래스 Object의 Dispatch table이 이 Method 구조체들을 포함하고 있을것이다.
method 관련 Runtime함수들
- Method method = class_getInstanceMethod(Class class, SEL sel)
: Method 구조체를 얻어내는 함수
- SEL sel = method_getName(Method method)
: SEL를 얻어내는 함수
- IMP imp = method_getImplementation(Method method)
: IMP를 얻어내는 함수
- method_setImplementation(Method method, IMP imp)
: 해당 Method에 IMP를 설정
Selector에 대응되는 IMP변경 코드
void killEmployee(id self, SEL _cmd)
{
NSLog(@"I'd rather kill you than pay you");
}
method_setImplementation(method, (IMP)killEmployee);
*참조
- http://pole2win.tistory.com/entry/Objective-C-objects
- http://pole2win.tistory.com/entry/Objective-C-dispatch
'IOS > Objective-C' 카테고리의 다른 글
GCD(Grand Central Dispatch)(2) (0) | 2016.12.19 |
---|---|
GCD(Grand Central Dispatch)(1) (0) | 2016.12.19 |
Key-Value Coding(1) (0) | 2016.12.07 |
Collections의 weak reference (0) | 2016.10.02 |
NSString과 NSMutableString의 copy (0) | 2016.02.18 |