Class objects и Objective-C runtime
При компиляции программы на Objective-C компилятор для каждого введенного класса автоматически создает так называемый class object — полноценный объект, содержащий в себе всю информацию о данном классе, включая название, суперкласс, список методов и instance-переменных.
При этом такой объект является полноценным объектом, то есть ему можно посылать сообщения, передавать в качестве параметра.
Одной из особенностей class object’а является то, что он поддерживает все методы класса NSObject, то есть когда ему посылается сообщение, то в начале идет поиск среди методов класса, а если метод не найден, то поиск продолжается среди instance-методов класса NSObject.
Ещё одной интересной особенностью является возможность инциализации class object’ов — в начале работы приложения каждому class object’у посылается сообщение (класса) initialize.
Это сообщение гарантированно посылается каждому class object’у, причем всего один раз и до того, как ему будет послано любое другое сообщение. Простейшим примером примененния такого сообщения является реализация Singleton’ов — именно в методе initialize следует создать тот самый единственный экземпляр объекта и запомнить его в static-переменной.
Если посмотреть на Objective-C runtime от Apple, то мы найдем большое количество С-функций, служащих для работы с классами (непосредственно во время выполения программы).
Наиболее интересными являются следующие:
Method class_getInstanceMethod( Class aClass, SEL aSelector ); Method class_getClassMethod ( Class aClass, SEL aSelector ); struct objc_method_list * class_nextMethodList(Class theClass, void ** iterator); void class_addMethods ( Class aClass, struct objc_method_list * methodList ); void class_removeMethods ( Class aClass, struct objc_method_list * methodList ); unsigned method_getNumberOfArguments ( Method method ); unsigned method_getSizeOfArguments ( Method method ); unsigned method_getArgumentInfo ( Method method, int argIndex, const char ** type, int * offset ); Ivar class_getInstanceVariable ( Class aClass, const char * aVariableName );
Функция class_getInstanceMethod возвращает указатель на структуру (objc_method), описывающую заданный instance-метод данного класса.
Функция class_getClassMethod возвращает указатель на структуру (objc_method), описывающую заданный метод данного класса.
Функция class_nextMethodList возвращет один из списков методов для заданного класса. Приводимый ниже фрагмент кода позволяет перебрать все методы для данного класса.
void * iterator = 0; struct objc_method_list * mlist; // // Each call to class_nextMethodList returns one methodList // methodList = class_nextMethodList( classObject, &iterator ) while ( methodList != NULL ) { // …do something with the method list here… methodList = class_nextMethodList ( classObject, &iterator ); }
Функция class_addMethods позволяет добавлять новые методы к заданному классу.
Функция class_removeMethods позволяет убирать методы из заданного класса.
Функция method_getNumberOfArguments Возвращает количество аргументов для заданного метода.
Функция method_getSizeOfArguments возвращает размер места на стеке, занимаемого всеми аргументами данного метода.
Функция method_getArgumentInfo возвращает информацию об одном из аргументов для заданного метода..
Функция class_getInstanceVariable возвращает информацию об instance-переменной класса в виде указателя на структуру objc_ivar.
Для кодирования информации о типах используется специальное строковое представление, однозначно сопоставляющее каждому типу данных некоторую строку. Явно получить такую строку для проивзольного типа можно при помощи конструкции @encode ().
char * buf1 = @encode ( int ** ); char * buf2 = @encode ( struct key ); char * buf3 = @encode ( Rectangle );
Автор: Алексей Боресков
Если вам понравилась статья, подпишитесь на RSS!
