"Вызов метода" ИЛИ "отправка сообщения" в Objective C
В C или любом языке на основе ECMAscript вы вызываете публичный метод или функцию на объект. Но в документации для Objective C нет публичных вызовов методов, а только отправка сообщений.
Есть ли что-то не так, думая, что когда вы отправляете сообщение в ObjC, вы на самом деле вызываете публичный метод для объекта.?
Ответы
Ответ 1
Теоретически, они разные.
Практически, не так много.
Они отличаются друг от друга в Objective-C, объекты могут не отвечать на сообщения или пересылать сообщения на разные объекты или что-то еще. В таких языках, как C, вызовы функций действительно просто прыгают в определенное место в памяти и выполняют код. Там нет динамического поведения.
Однако в стандартных случаях использования, когда вы отправляете сообщение объекту, метод, в котором отображается сообщение, обычно вызывается. Таким образом, примерно в 99% случаев отправка сообщения приведет к вызову метода. Таким образом, мы часто говорим "вызов метода", когда мы действительно имеем в виду "отправить сообщение". Таким образом, практически, они почти всегда одинаковы, но они не обязательно должны быть.
Некоторое время назад я занимался философскими вопросами по этой теме и писал об этом: http://davedelong.tumblr.com/post/58428190187/an-observation-on-objective-c
изменить
Чтобы напрямую ответить на ваш вопрос, обычно нечего делать, говоря "вызов метода" вместо "отправки сообщения". Однако важно понимать, что существует очень значительная разница в реализации.
(И как в сторону, мое личное предпочтение - сказать "вызывать метод на объекте" )
Ответ 2
Из-за Objective-C диспетчеризации динамических сообщений отправка сообщений фактически отлична от вызова функции C или метода С++ (хотя в конечном итоге будет вызываться функция C). Сообщения отправляются через селекторы к принимающему объекту, который либо отвечает на сообщение, вызывая IMP
(указатель функции C), либо пересылая сообщение своему суперклассу. Если ни один класс в цепочке наследования не отвечает на сообщение, генерируется исключение. Также возможно перехватить сообщение и переслать его в совершенно другой класс (это то, что делают подклассы NSProxy
).
При использовании Objective-C нет большой разницы между отправкой сообщений и вызовом метода в стиле С++, но есть несколько практических последствий системы передачи сообщений, о которой я знаю:
- Поскольку обработка сообщений происходит во время выполнения, а не во время компиляции, нет способа компиляции, чтобы узнать, реагирует ли класс на какое-либо конкретное сообщение. Вот почему вы обычно получаете предупреждения компилятора вместо ошибок, например, когда вы опечатываете метод.
- Вы можете безопасно отправить любое сообщение в
nil
, разрешив такие идиомы, как [foo release]
, не беспокоясь о проверке NULL.
- Как сообщает @CrazyJugglerDrummer, отправка сообщений позволяет отправлять сообщения по множеству объектов одновременно, не беспокоясь о том, будут ли они отвечать на них. Это позволяет использовать неофициальные протоколы и отправлять сообщения всем объектам в контейнере.
- Я не уверен на 100%, но я думаю, что категории (добавление методов к уже существующим классам) становятся возможными благодаря динамической отправке сообщений.
- Отправка сообщений позволяет пересылать сообщения (например, с подклассами
NSProxy
).
- Отправка сообщений позволяет делать интересные хакерские атаки низкого уровня, такие как метод swizzling (обмен реализациями методов во время выполнения).
Ответ 3
Нет, нет ничего плохого в том, чтобы думать об этом так. Они называются сообщениями, потому что они являются слоем абстракции над функциями. Часть этого исходит от системы типа Objective C. Лучшее понимание сообщений помогает:
полный источник в wikipedia (я выбрал некоторые из наиболее актуальных проблем)
Внутренние имена функции редко используется напрямую. В общем, сообщения преобразуются в функцию вызовов, определенных в Objective-Cбиблиотека времени исполнения. Это не обязательно известный в момент ссылки, какой метод будет называться потому, что класс приемника (объект отправляется сообщение) не нужно знать до тех пор, пока во время выполнения.
из той же статьи:
Модель Objective-Cобъектно-ориентированное программирование при передаче сообщения объекту экземпляров. В Objective-C нет вызвать метод; один отправляет сообщение. Объект, к которому сообщение направлено - приемник - не гарантируется сообщение, а если нет, то просто вызывает исключение. Программирование в стиле Smalltalk позволяет сообщениям не выполняться, с методом, разрешенным к его реализации во время выполнения. Для Например, сообщение может быть отправлено на сбор объектов, к которым только ожидается, что некоторые ответят, не опасаясь создания времени выполнения ошибки. (Платформа Cocoa принимает Преимущество этого, поскольку все объекты в Приложение Cocoa отправляется awakeFromNib: сообщение как запуска приложений. Объекты могут ответить, выполнив любой инициализация, требуемая при запуске.) Передача сообщений также не требует что объект должен быть определен при компиляции время.
Ответ 4
При вызове функции C компилятор заменяет селектор вызовом функции, а выполнение переходит в ответ на вызов функции.
В Objective-C методы динамически связаны с сообщениями, что означает, что имена методов разрешены для реализаций во время выполнения. В частности, объект проверяется во время выполнения, чтобы увидеть, содержит ли он указатель на реализацию для данного селектора.
Как следствие, Objective-C позволяет загружать и связывать новые классы и категории во время его запуска, а также выполнять такие функции, как swizzling, категории, прокси объектов и другие. Ничего из этого не возможно в C.
Ответ 5
Преподавал это в моем классе Java. Я бы сказал, что они имеют только реалистичные различия в многопоточных сценариях, где передача сообщений является очень законной и часто используемой техникой.