Зачем использовать id, когда мы можем просто использовать NSObject? - PullRequest
36 голосов
/ 26 октября 2011

Я знаю, что когда мы хотим создать объект с неизвестным значением, мы используем id.Однако мне любопытно, почему Apple выбрала идентификатор, который определяет его значение во время выполнения, когда каждый объект является подклассом NSObject.Так что вместо id delegate мы могли бы использовать NSObject *delegate Кто-нибудь знает почему?Спасибо.

Ответы [ 4 ]

39 голосов
/ 26 октября 2011

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

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

Со строгими / правильными типами компилятор может подключиться и помочь вам, что прекрасно, потому что ObjC очень динамичныйlanguage.

id особенно полезен при использовании (или построении) типов коллекций.Добавление объекта не будет проблемой, если вы не определили новый корневой тип (не наследуется от NSObject).Для получения значения из коллекции потребовалось бы приведение типа, если бы мы использовали его как нечто отличное от нашего базового класса (NSObject).

Objective-C не поддерживает обобщенные элементы - вы, например, не можете объявить NSArray из NSString с.Вы можете заполнить NSArray с помощью NSString s и передать это через id для более естественного письменного стиля, когда безопасность типов не сохраняется (а-ля 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;
11 голосов
/ 26 октября 2011

каждый объект является подклассом NSObject

Это неверное утверждение.Вы можете создавать объекты, которые не наследуются от NSObject.на самом деле это не рекомендуется, но возможно.

NSProxy является примером - он не наследуется от NSObject.

3 голосов
/ 26 октября 2011
typedef struct objc_object {
    Class isa;
} *id;

Выше приведено фактическое определение id в языке Objective-C.Система времени выполнения Objective C построена вокруг id и Class.Ничего общего с NSObject или обычным суперклассом не имеет.

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocObjectsClasses.html#//apple_ref/doc/uid/TP30001163-CH11-SW3

NSObject Class

NSObject является корневым классом и поэтому не имеетсуперкласс.Он определяет базовую структуру для объектов Objective-C и взаимодействия объектов.Он передает классам и экземплярам классов, которые наследуют от него, возможность вести себя как объекты и взаимодействовать с системой времени выполнения.

Класс, которому не нужно наследовать какое-либо специальное поведение от другого классатем не менее следует сделать подклассом класса NSObject.Экземпляры класса должны, по крайней мере, иметь возможность вести себя как объекты Objective-C во время выполнения. Наследовать эту способность от класса NSObject намного проще и гораздо надежнее, чем заново изобретать ее в новом определении класса.

Я думаю, это потому, что изначально C не C++ (или другие более строгие языки ввода).

2 голосов
/ 26 октября 2011

каждый объект является подклассом NSObject

Это не правильно.Вы можете создать объект, который расширяется из ничего, как корневой класс.

Возможно, именно поэтому был введен идентификатор.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...