메세징 기법 요약
obj-c
는 다른 객체지향 언어와 달리메세징 기법
을 사용한다.
- 코드 작성 시에는 메세지 전달 구분을 작성하고,
- 빌드 후 실행시키면
런타임 라이브러리
함수들을 이용해 메세지 처리부분을 찾아가서 실행시킨다.
isa
참고링크
실제 런타임 시에 메세지 처리 함수를 어떻게 찾아갈까?
- 모든
객체
들은isa
라고하는 멤버변수를 갖고 있다.
isa
는 객체를 생성한클래스 오브젝트
를 가리키는 포인터 변수다.
//클래스 오브젝트 포인터를 Class로 typedef typedef struct objc_class *Class; //오브젝트는 자신을 할당한 클래스 오브젝트에 대한 포인터 변수를 가짐 (isa) typedef struct objc_object { Class isa; } *id;
클래스 오브젝트?
인스턴스 오브젝트
vs클래스 오브젝트
- 오브젝트에는 해당 오브젝트를 할당한 클래스 오브젝트의 주소를 담는 포인터 변수
isa
가 있다고 했다.
- 클래스면 클래스지
클래스 오브젝트
는 또 뭘까?
- Obj-c에는 클래스의 인스턴스 뿐만 아니라, 클래스 자체도 하나의 오브젝트로 존재한다.
지금까지 인스턴스 오브젝트 할당 시 당연하게도 [클래스명 alloc]라는 메세지 구문으로 할당했는데, 클래스명이라고 적었던 것이 사실은
클래스 오브젝트
에 메세지를 전달하는 것을 알고나면 이해가 된다.RacingCar *firstCar = [[RacingCar alloc] init]; RacingCar *secondCar = [[RacigCar alloc] init];
클래스 오브젝트
에alloc
메세지를 보내면 객체를 할당한 뒤 isa 멤버변수에 오브젝트를 할당한 자기자신 즉, 클래스 오브젝트의 주소를 담고 반환한다.
[firstCar pitIn];
- 다음은 할당된
인스턴스 오브젝트
에 메세지를 보내는 구문이다.
- 해당 구문은 런타임에
인스턴스 오브젝트
의isa
를 통해클래스 오브젝트
를 얻고, 클래스 오브젝트의디스패치 테이블
을 참조하여셀렉터
에 대응하는 함수를 찾아서 호출하게 된다.
디스패치 테이블
클래스 오브젝트에서 셀렉터에 대응하는 함수 주소를 어떻게 찾을까?
- 클래스 오브젝트는 해당 클래스가 구현하는 모든 메소드의 정보를 가지고 있고, 이것을
Dispatch table
이라고 한다.
- 인스턴스 오브젝트가 메세지를 호출하면
isa
를 통해 클래스 오브젝트를 얻는다.
- 클래스 오브젝트의
디스패치 테이블
에서셀렉터
에 대응하는 메소드를 찾는다.
- 대응하는 메소드를 찾지 못했으면
superclass
의 디스패치 테이블을 본다. (상속받은 클래스 참조)
- 2~3 반복.
- 찾지못하고
루트 클래스 오브젝트
에 도달하면 대응하지 못한다고 판단하고 이에 맞는 런타임 함수를 호출.

루트 클래스
어떠한 클래스도 상속받지 않는 최상위 클래스를
루트 클래스
라고 한다.코코아 프로그래밍 환경에서 루트 클래스는 항상
NSObject
혹은 NSProxy
다. (대부분 NSObject를 상속)루트 클래스인
NSObject 클래스
는 NSObject 프로토콜
을 채택하므로 프로토콜에 명시된 메소드는 반드시 구현되어야 한다.메타 클래스
클래스 오브젝트
도 하나의 오브젝트이므로 역시 자신을 생성한 클래스 오브젝트의 주소를 담는 isa
를 갖는다.- 클래스 오브젝트를 생성하는 클래스 오브젝트를
메타클래스 오브젝트
라고 한다.
- 모든 메타클래스 오브젝트의
isa
는 루트 클래스의 '메타클래스 오브젝트'를 가리킨다. - (루트 메타클래스 오브젝트 자신도 포함)
결론
지금까지의 내용을 종합해보면
인스턴스 오브젝트
, 클래스 오브젝트
, 메타클래스 오브젝트
와의 관계는 아래 그림과 같이 정리할 수 있다.