"Вызов метода" ИЛИ "отправка сообщения" в 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. Я бы сказал, что они имеют только реалистичные различия в многопоточных сценариях, где передача сообщений является очень законной и часто используемой техникой.