Как объективная среда выполнения 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, что приведет к тому, что байты этого объекта будут интерпретироваться как новый тип (Внимание: это продвинутый материал, поэтому, пожалуйста, будьте осторожны!)

Другие вопросы по тегам