2009-07-02 1 views
4

Я только начал читать учебники Objective-C, и есть раздел на «отправив сообщение nil»:Что означает «отправка сообщения в нуль», и почему это особый случай?

Есть несколько моделей в Какао , что воспользоваться этим фактом. Значение вернулся из сообщения на ноль также может быть действительным:

Что это значит? Кажется, я не понимаю.

ответ

5

Вы можете отправить любое сообщение в ноль. Ничего не произошло.

Что именно вы не понимаете в этих документах?

+1

Что такое ноль? Вы устанавливаете значение null для метода объекта? или отправить значение null в сообщение? что такое messagE? – Blankman

+0

"nil" - это нулевой объект. Если вы знакомы с Java, «отправка сообщения в nil» эквивалентна «вызову метода на null» в Java, за исключением того, что в Java вы получаете исключение NullPointerException, тогда как в Objective-C ничего не происходит. Таким образом, вы можете смело сделать что-то вроде «[nil doThis: withThis]», и программа не будет разбиваться (метод просто вернет нуль). – mipadi

+1

Не совсем. Nil равно 0, это не объект. Вот почему вы можете сделать то же самое с методами, возвращающими целочисленное значение. Существует специальный объект NSNull, который можно использовать в классах коллекций, но он не равен нулю. –

1

Он делает то, что вы ожидаете: ничего.

+3

Очень мало людей, знакомых с популярными языками, такими как Java, C# или C++, ожидали, что это ничего не сделает. Они ожидали бы исключения или крушения. – bacar

8

Специальная обработка nil означает, что вы можете сделать следующее:

SomeClass * someObject; 
someObject = nil; 
[someObject doSomething]; 

И вы можете быть уверены, что ничего не произойдет.

Теперь, почему это важно?

В Objective-C отправка сообщения объекту означает указание этому объекту что-то сделать или запрос об этом объекте для некоторой информации. Некоторые примеры:

[someObject updateRecords]; // 1 
x = [someObject size];  // 2 

Line 1 посылает сообщение someObject под названием updateRecords, а линия 2 посылает один и тот же объект сообщение под названием size, который, как ожидается, возвращает значение. Эти сообщения сводятся к вызовам методов, а фактический код, который заканчивается запуском, определяется системой времени выполнения Objective-C, поскольку Objective-C является динамически типизированным языком.

Чтобы определить, какой метод вызывать, система времени выполнения считывает информацию с адреса рассматриваемого объекта (someObject, в приведенных выше примерах), чтобы определить, какой класс является экземпляром. Используя эту информацию, она может искать соответствующий метод для вызова, и когда все, что было выяснено, выполняет код в методе.

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

+1

Итак, почему в http://www.raywenderlich.com/2696/how-to-debug-memory-leaks-with-xcode-and-instruments-tutorial они говорят, что «отправка сообщения на освобожденную память вызывает сбой»? – onmyway133

+2

Отправка сообщения в освобожденную память (также известную как зомби) может произойти, если вы отпустите объект, но сохраните указатель на старую ячейку памяти. Например: '[someObject release]; [someObject someMethod]; '. Это сильно отличается от 'someObject = nil; [someObject someMethod]; 'Даже если установка someObject в nil может освободить его в среде GC, действие установки его на nil также не позволит вам отправить сообщение в память * deallocated *. –

2

Отличная идея обмена сообщениями nil по сравнению с другими языками, такими как C#, заключается в том, что вы можете писать код, который выполняет множественные вызовы методов, без необходимости тестировать нуль на каждом шаге.

id obj1 = [SomeClass object]; 
id obj2 = [obj1 doSomething]; 
id obj3 = [obj2 anotherMethod]; 

id thingICareAbout = [obj3 doSomethingElse]; 

Если пройти несколько шагов, чтобы добраться до thingICareAbout, это экономит много ненужных строк кода, чтобы не проверить, если obj1, obj2 и так далее равны нулю перед их использованием. Вы можете просто проверить, нет ли thingICareAbout в конце, если вам нужно. Иногда вам даже не нужно этого делать, если ваш код по-прежнему работает, когда он равен нулю (или 0 для примитивных значений).

В C# вам нужно было бы явно проверить, равен ли каждый объект нулю, настроить обработку исключений вокруг этого блока кода или просто надеяться, что ни один из промежуточных объектов никогда не будет равен нулю.

Еще одна вещь, о которой я только что узнал, - это то, что 10.5 изменили это поведение - раньше было безопасно только для целых чисел и указателей на объекты, а не на структуры или значения с плавающей запятой. Из-за этого вы можете увидеть дополнительную проверку ошибок, когда вы смотрите на другой код.

9
  • nil - это, в основном, нулевой указатель (т. Е. Это нуль, сохраненный в указателе).
  • Все сообщения в nil являются законными (они не вызовут сбой), но они ничего не делают.
  • Все сообщения nil возвращают ниль, или 0, или 0.0, или NO, в зависимости от типа возврата.
+1

Точка 3 зависит от времени выполнения. В более ранних версиях документации в документации говорилось, что вы не можете полагаться на возвращаемое значение обмена сообщениями nil, если метод возвратил переменные float, double или more-than-natural-word. – dreamlax