Objective-C에서 생성 한 클래스의 인스턴스는 id 형식의 변수에 저장할 수있었습니다. id 형식은 void *를 닮은 존재로, 클래스에 관계없이 인스턴스를 저장하는 일반적인 객체 형입니다. 따라서 id 형의 변수의 실체는 컴파일 타임이 아닌 런타임에 결정되는 특징이 있습니다.
그러나 런타임에 인스턴스를 조사하는 것은, 예를 들어 메소드를 호출하기 위해 객체에 메시지를 보내도 그 메시지에 대응 한 메소드가 존재하지 않는다는 수 있습니다. 다음과 같은 프로그램은 그 전형적인 예 이지요.
#import <stdio.h> #import <objc / Object.h> @interface A : Object - (void) Write; @end @implementation A - (void) Write { printf ( "I am the born of my sword \ n"); } @end int main () { id obj1 = [A new]; id obj2 = [Object new]; [obj1 Write]; [obj2 Write]; // 런타임 오류 return 0; }
이 프로그램은 선언 한 A 클래스의 인스턴스를 생성 해 Write 메세지를 전송하고 있습니다. 마찬가지로 Object 클래스의 인스턴스를 생성하고 Write 메시지를 보낼 수 있습니다. Object 클래스는 Write 메서드 등은 존재하지 않지만, 컴파일 할 수 있습니다. 이것은 Objective-C 메시지의 호출이 실행될 때 판정되는 것을 나타냅니다.
컴파일 된 프로그램을 실행하면 obj1 변수에 대한 Write 메시지의 전송은 성공하지만, obj2 변수는 Object 클래스의 오브젝트이므로 Write 메소드는 존재하지 않습니다. 따라서 obj2 변수에 대해서 Write 메세지를 전송해도 런타임 오류가 발생하는 것입니다.
이처럼 id 형식은 일반적이고, 객체라는 단위로 클래스 형의 인스턴스 데이터를 참조하려면 편리 합니다만 특정 클래스를 상정하고 취급하는 경우에 적합합니다. 특히 대규모 프로그램되어 많은 인스턴스를 생성하는 경우는 id 형식을 대량으로 선언하면 어떤 변수에 어느 클래스 형의 객체를 저장하고 있는지 여부를 알 수 없게되어 버립니다 .
형태의 판정을 런타임이 아닌 컴파일 할 수 있으면 컴파일러가 형식을 체크하는 정보로서 이용 될 수 있습니다. 구현에 의존하는 문제이지만, 형식이 컴파일시에 드러나면 메시지 식을 검사하여 대상의 클래스 형에 지정된 메서드가 존재하는지 여부를 확인하고 필요에 따라 경고를 발생시킬 수있는 것입니다. 컴파일시에 정적으로 클래스 형을 판정하기 위해서는 id 형식이 아니라 클래스 이름을 형태로 클래스 형의 포인터를 사용해 인스턴스를 참조합니다. 예를 들어, Point 클래스 전용 변수는 Point 형 포인터로 선언합니다.
#import <stdio.h> #import <objc / Object.h> @interface A : Object - (void) Write; @end @implementation A - (void) Write { printf ( "A. Write Method \ n"); } @end int main () { A * obja = [A new]; [obja Write]; [obja free]; return 0; }
이 프로그램은 선언 한 A 클래스의 인스턴스를 만들고 A * 형태의 변수 obja에 저장합니다. 지금까지는 id 형식에 객체를 저장하고 왔지만,이 프로그램에서는 명시 적으로 A 클래스 형인 것을 지정하고 있습니다.
클래스 형의 포인터는 메모리상의 실체 인 인스턴스의 주소를 저장하는 데 사용됩니다. id 형도 인스턴스의 주소를 저장하기위한 것이지만, 형식은 클래스 형식을 지정하는 것이 분명하다. 보통 Objective-C 클래스 형 변수는 구조 체형 변수와 정적 변수로 선언 할 수 없습니다. 클래스 형의 변수는 반드시 포인터로 취급되어야 것입니다.
SmallTalk를 원류로하는 Objective-C 언어는 비교적 id 형식이 사용되는 경향이 있지만, 현대의 객체 지향 언어의 표준적인 기술 방법에서 생각하면, 클래스 형을 명기 한 변수를 사용하는 것이 좋습니다. id 형식을 사용하는 것은 alloc과 init와 같은 반환 값이 다양 화되고있는 메소드 등에 한정해야합니다.
는 클래스 변수는 그 클래스 형의 인스턴스에 대한 포인터 밖에 대입 할 수없는 것일까 요. C 언어의 원리를 생각하면, 결국은 포인터에 지나지 않기 때문에 그런 것은 아닙니다.