Как объективная среда выполнения C ищет определенные сообщения?
Я новичок в цели C и из C/C++ фона, я стараюсь понять, насколько динамична цель C.
Программирование с Objective-C Стр. 38
Рассмотрим следующий код:
id someObject = @"Hello, World!";
[someObject removeAllObjects];
В этом случае, someObject
будет указывать на NSString
экземпляр, но компилятор ничего не знает об этом экземпляре, кроме того факта, что это какой-то объект. removeAllObjects
сообщение определяется некоторыми объектами Cocoa или Cocoa Touch (такими как NSMutableArray
) поэтому компилятор не будет жаловаться, хотя этот код будет генерировать исключение во время выполнения, поскольку объект NSString не может ответить на removeAllObjects.
Сообщение removeAllObjects определяется некоторыми объектами Cocoa или Cocoa Touch (например, NSMutableArray), поэтому компилятор не будет жаловаться.
Означает ли это, что во время выполнения будут искать все реализованные методы? Если да, не влияет ли это на производительность?
Пожалуйста, предложите, если мое понимание неверно.
Благодарю.
1 ответ
Ответ TheEye совершенно неправильный, и я думаю, что для новичков в Objective-C важно понять, как это на самом деле работает.
В Objective-C нет методов. Вы отправляете сообщения объектам. Это не просто небольшая разница в синтаксисе, это принципиально иная философия.
Что на самом деле происходит, когда вы отправляете removeAllObjects
сообщение объекту (независимо от того, объявлено ли оно как id или NSString*), среда выполнения просматривает указатель isa (is-a) объекта во время выполнения, который указывает на определение этого объекта.
Каждое определение объекта имеет список селекторов сообщений, которые реализует объект. Для производительности во время выполнения система кэширует селекторы. Поэтому он проверит, содержит ли кеш этот селектор. Если это произойдет, среда выполнения перейдет к этому месту и начнет выполнять код, найденный там. Он также проверит цепочку унаследованных классов, чтобы увидеть, реализует ли какой-либо из них сообщение.
Если он не может найти сообщение, он отправит селектор forwardInvocation:
, Это происходит для всех неизвестных сообщений. Так уж получилось, что реализация NSObject по умолчанию forwardInvocation:
Запускает doesNotRecognizeSelector:
который потерпит крах.
Вы можете проверить это самостоятельно, внедрив forwardInvocation:
на свой собственный класс и ничего не делать. Затем попробуйте отправить случайные селекторы в экземпляр вашего класса. Вы увидите, что ошибок не возникает. Это позволяет создавать прокси-объекты, которые проверяют, фильтруют или изменяют сообщения, предназначенные для другого объекта. Вы также можете полностью выдавать себя за другой класс.
Тип переменной, объявленной в коде, является лишь подсказкой, поэтому компилятор может помочь вам перехватывать ошибки во время компиляции. Во время выполнения это не имеет большого значения. Objective-C только смотрит на указатель isa, чтобы определить класс объекта и, следовательно, какие селекторы сообщений он поддерживает.
Вот почему вы можете переопределить класс во время выполнения, добавить новые методы в класс и т. Д. Вы даже можете изменить тип объекта во время выполнения, изменив указатель isa, что приведет к тому, что байты этого объекта будут интерпретироваться как новый тип (Внимание: это продвинутый материал, поэтому, пожалуйста, будьте осторожны!)