указатель на таблицу диспетчеризации, связанную с его классом. Этот неявный указатель
называется указателем связи isa (isa link) (не смешивать с условием «быть экземпляром»
(is-a relation) для классов). Пересылка сообщения в языке Objective-C вроде следующего
выражения из задачи о восьми ферзях
[neighbor checkrow: row column: column]
преобразуется компилятором языка Objective-C1 в код
objc_msgSend(neighbor, "checkrow:column:", row, column)
Функция objc_msgSend, называемая функцией пересылки сообщений, следует по
указателю связи isa для первого аргумента с тем, чтобы найти соответствующую таблицу
диспетчеризации. Затем функция пересылки сообщений просматривает таблицу
диспетчеризации в поисках записи, соответствующей селектору. Если такая запись
найдена, вызывается нужный метод. Если подобного метода не обнаружено, поиск
продолжается в таблице диспетчеризации надкласса. Если в конце концов достигнут
корневой класс Object, а метод так и не найден, выдается сообщение об ошибке этапа
выполнения.
Кэширование методов
Хотя для языков программирования с динамическими типами данных таблицы
диспетчеризации являются более экономичными по объему, чем таблицы виртуальных
методов, затраты времени на вызов метода значительно больше. Кроме того, эти затраты
пропорциональны глубине наследования. Если бы эти накладные расходы были
непреодолимы, то разработчики скорее отказались бы вообще от механизма наследования,
согласившись на потерю мощи ради выигрыша в эффективности.
К счастью, мы можем в значительной степени снизить эти потери во время выполнения
программы за счет следующего простого подхода. Будем хранить единую для всей
системы кэш-таблицу методов, к которым недавно осуществлялся доступ. Она
индексируется хэш-кодом
2
определяемым по селектору метода. Каждая запись в кэш-таблице представляет собой
тройку, состоящую из указателя на класс (для этой цели служит собственно таблица
диспетчеризации), значения селектора и указателя на метод.
Когда функцию пересылки сообщений просят найти метод, который соответствует паре
«класс–селектор», она прежде всего осуществляет поиск в кэш-таблице (рис. 21.6). Если
запись в кэше по месту расположения хэш-кода соответствует требуемым селектору и
классу, то соответствующий метод может быть выполнен немедленно. Если нет —
проводится процесс поиска, описанный выше. В результате поиска непосредственно перед
выполнением найденного метода происходит обновление кэш-таблицы. При этом запись,
содержавшаяся по месту соответствующего хэш-кода (рассчитываемому по селектору
2
Хэширование (hashing) — метод приближенного индексирования для сокращения поиска нужных данных.
При хэшировании каждому данному ставится в соответствие хэш-код (hash-code), который используется для
упорядочивания данных в хэш-таблице и служит селектором при их поиске. Характерная черта хэш-кода
состоит в том, что он, вообще говоря, не является уникальным (то есть различные данные могут порождать
при вычислениях одинаковый хэш-код). Однако он быстро вычисляется и позволяет значительно сократить
область поиска данных. Примером хэширования служит словарь с закладками по месту смены первой буквы
слов. Здесь первая буква слова выступает в качестве его хэш-кода. — Примеч. перев.
PDF created with pdfFactory Pro trial version www.pdffactory.com