为什么使用id,当我们可以只使用NSObject?
我知道,当我们想创build一个未知的值对象,我们使用ID。 不过,我很好奇,为什么苹果select在运行时决定它的值的id,当时每个对象都是NSObject的子类。 所以,而不是id delegate
我们可以使用NSObject *delegate
有谁知道为什么? 谢谢。
id
擦除types,相当于说“这个对象响应翻译可见的select器”。 当然,当你擦除types时(以及当你input它们的时候), 你有责任确保你的程序是正确的。
如果types是NSObject
,那么如果select器没有在NSObject的接口或它所采用的协议中声明,编译器会说“NSObject可能不响应select器 ”。 在这种情况下,您也可以添加一个types转换来将其转换为您所期望的types。
使用严格/正确的types,编译器可以踢出来帮助你,这很好,因为ObjC是一种非常dynamic的语言。
id
在使用(或构build)集合types时特别有用。 添加一个对象不会是一个问题,除非你定义了一个新的根types(不从NSObjectinheritance)。 从集合中获取值需要一个types转换(typecast),如果我们要把它作为基类(NSObject)之外的东西来使用的话。
Objective-C不支持generics – 例如,你不能声明NSString
的NSArray
。 你可以使用NSString
填充一个NSArray
,并且在types安全性不被保留的情况下(lagenerics),通过id
传递一个更自然的书面风格。
所以,让我们用一些真实的代码来展开。
例子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;
每个对象都是NSObject的一个子类
这是一个不正确的说法。 您可以创build不从NSObjectinheritance的对象。 这不是真的推荐,但它是可能的。
NSProxy
是一个例子 – 它不从NSObjectinheritance。
typedef struct objc_object { Class isa; } *id;
以上是Objective-C语言中id
的实际定义。 Objective-C运行时系统是围绕id
和Class
构build的。 没有什么必须与NSObject或普通的超类。
NSObject类
NSObject是一个根类,所以没有超类。 它定义了Objective-C对象和对象交互的基本框架。 它赋予类inheritance的类和实例的能力,作为对象的行为,并与运行时系统合作。
不需要从另一个类inheritance任何特殊行为的类应该成为NSObject类的一个子类。 类的实例必须至less具有在运行时类似于Objective-C对象的能力。 从NSObject类inheritance这个function比在新的类定义中重新创build它要简单得多,也更可靠。
我想,这是因为它最初是C
而不是C++
(或其他更严格的打字语言)。
每个对象都是NSObject的一个子类
这是不正确的。 你可以创build一个从根本上没有任何东西的对象。
这也许是为什么id被介绍了。