Ответ 1
id
стирает тип, и он эквивалентен тому, что "этот объект отвечает на любой селектор, видимый для перевода". конечно, вы несете ответственность за то, чтобы ваша программа была правильной, когда вы удаляете типы (а также при их отображении).
Если тип был NSObject
, тогда компилятор сказал бы: "NSObject может не отвечать на селектор", если селектор не был объявлен в интерфейсе NSObject или протоколах, которые он принимает. В этом случае вы также можете добавить приведение типов к тому, что вы ожидаете.
Со строгими/правильными типами компилятор может ударить и помочь вам, что отлично, потому что ObjC - очень динамичный язык.
id
особенно полезен при использовании (или создании) типов коллекций. Добавление объекта не будет проблемой, если вы не определили новый корневой тип (не наследуемый от NSObject). Получение значения из коллекции потребует машинного перевода, если мы будем использовать его как нечто иное, чем наш базовый класс (NSObject).
Objective-C не поддерживает дженерики - вы не можете, например, объявить NSArray
из NSString
s. Вы можете заполнить NSArray
с помощью NSString
и передать это через id
для более естественного письменного стиля, когда безопасность типов не сохраняется (a la generics).
Итак, давайте разберем это с помощью некоторого реального кода.
Пример A
NSString * string = [array objectAtIndex:0]; // << trust me (via id)
return [string length];
-or-
return [[array objectAtIndex:0] length]; // << trust me (via id)
Пример B
А теперь скажем, id
недоступен, и мы исправим все наши предупреждения для компилятора, потому что это правильно:
NSString * string = (NSString*)[array objectAtIndex:0]; // << typecast == trust me
return [string length];
-or-
return [(NSString*)[array objectAtIndex:0] length]; // << typecast == trust me
id
не определяет его значение во время выполнения, а также не NSObject. Объекты ObjC не выполняют неявных рекламных акций, они просто передают указатель без официального продвижения.
В связи с вашим примером я фактически объявляю свои делегаты и параметры как NSObjects с протоколами:
NSObject<MONShapeDelegate>* delegate;