Возможна ситуация с отправкой сообщения объекту, у которого нет соответствующего метода.

Если такое случится, последствия могут быть фатальными: ваше приложение может просто аварийно завершиться. Единственный защитник от таких непредвиденных обстоятельств — компилятор; но это не слишком сильный защитник. В некоторых случаях компилятор предупредит вас, что, возможно, вы делаете что-то нежелательное; но в других случаях компилятор с радостью позволит вам наступить на эти грабли.

Вот ситуация, в которой компилятор действительно спасет вас от самого себя:

NSString* s = @"Hello, world!";
[s rockTheCasbah];

Класс NSString не имеет метода rockTheCasbah. До появления механизма ARC компилятор разрешил бы компиляцию этого кода, но предупредил бы о том, что вы сами ищете себе проблемы. Однако при наличии механизма ARC компилятор с негодованием отвергает вашу попытку с сообщением о фатальной ошибке “No visible 0interface for ‘NSString’

declares the selector ‘rockTheCasbah’”. (Компилятор с механизмом ARC гораздо строже, так как механизм ARC должен работать с управлением памятью, а при разрешении отправлять бессмысленные сообщения это не удается делать эффективно.)

Немного замутив воду, мы можем проскользнуть мимо строгого механизма ARC. Предположим, что у нас есть класс MyClass, в котором объявлен метод rockTheCasbah. Тогда мы можем записать

MyClass* m = @"Hello, world!";
[m rockTheCasbah];

Мы говорим, что m — экземпляр класса MyClass, но на деле присваиваем этой ссылке экземпляр NSString. Это странное, но не строго запрещенное действие. Компилятор предупредит нас о неполной корректности этого присваивания (“incompatible pointer types”), но программу скомпилирует. Остается ехидно засмеяться и запустить программу на выполнение. И что получится?

Когда программа заработает и класс NSString получит сообщение rockTheCasbah, программа аварийно завершится с сообщением (в журнале консоли) о случившейся неприятности в виде

-[ NSCFConstantString rockTheCasbah]: unrecognized
selector sent to instance 0x8650.

Это сообщение детально описывает происшедшее.

  • Фраза о нераспознанном селекторе (unrecognized selector) является самой сутью происшедшего. Термин “селектор” грубо эквивалентен термину “сообщение”, так что это способ сказать, что определенному объекту послано сообщение, с которым он не в состоянии справиться.
  • -[ NSCFConstantString rockTheCasbah] описывает сообщение и его получателя, используя сокращение, о котором я говорил ранее: экземпляру NSCFConstantString послано сообщение экземпляра rockTheCasbah. (Описание NSString как NSCFConstantString представляет собой внутренние подробности языка.)
  • 0x8650 — значение указателя на экземпляр; это адрес в памяти, на который в действительности указывает указатель т.

 

Ситуация нераспознанного селектора приводит к генерации исключения, внутреннего сообщения о том, что при работе программы произошло что-то плохое. Код на Objective-C может “поймать” исключение, и тогда аварийное завершение не произойдет. Технически причина завершения работы программы не в том, что объекту отправлено сообщение, с которым тот не смог справиться, а в том, что не было перехвачено сгенерированное при этом исключение. Вот почему журнал сбоев может также гласить “Terminating арр due to uncaught exception” (завершение приложения из-за неперехваченного исключения).

 

В этом примере мы сознательно создали неприятности сами себе, чтобы продемонстрировать, что происходит, когда возникает ситуация нераспознанного селектора. Пример, конечно, достаточно надуманный, но последствия таковыми не являются. Я заверяю, что такая вещь рано или поздно случится и с вами, хотя, конечно, не преднамеренно. Это произойдет потому, что, как я сказал в начале этого раздела, ваша ссылка окажется не совсем тем, что вы о ней думаете. Существует множество путей, которыми может возникнуть такая ситуация; например, как я покажу в следующем разделе, вы можете случайно соврать компилятору о классе объекта, или компилятор может не иметь никакой информации о классе объекта, так что он даже не сможет предупреждать вас о сообщении, которое объект не в состоянии обработать. Следите за фразой “unrecognized selector”, когда ваша программа аварийно завершает работу, — теперь вы знаете, что это значит и как интерпретировать такое сообщение! Детали сообщения помогут вам понять, что именно не так и как исправить ситуацию.


Похожие статьи

 

 

 

Добавить комментарий