为什么使用id的时候我们只能使用NSObject?
我知道,当我们想创建一个未知的值对象时,我们使用id。然而,我很好奇苹果为什么选择在运行时决定它的值的id,当时每个对象都是NSObject的一个子类。所以,而不是id delegate
我们可以用NSObject *delegate
有谁知道为什么?谢谢。为什么使用id的时候我们只能使用NSObject?
id
消除类型,它等同于说“此对象响应任何对翻译可见的选择器”。当然,它是你的责任,以确保你的程序是正确的,当你擦除类型(以及当你对它们进行类型化时)。
如果类型为NSObject
,那么编译器会说“NSObject的可能不选择回应:”如果选择不是在NSObject的界面也采用了协议声明。在这种情况下,你也可以添加一个类型转换来将它转换为你期望的类型。
对于严格/正确的类型,编译器可以踢出来帮助你,这很好,因为ObjC是一种非常动态的语言。
id
在使用(或构建)集合类型时特别有用。除非您定义了新的根类型(不从NSObject继承),否则添加对象不会成为问题。如果我们要将它用作基类(NSObject)以外的其他类型,那么从集合中获取值将需要一个类型转换。
Objective-C不支持泛型 - 例如,您不能声明NSArray
的NSString
s。您可以使用NSString
填充NSArray
s,并通过id
传递此类型以获得更自然的书写样式,但不保留类型安全性(la泛型)。
所以,让我们用一些真实的代码来展开。
例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的
的子类,这是不正确的。你可以创建一个从根本上没有任何东西的对象。
这也许就是为什么id被引入。
typedef struct objc_object {
Class isa;
} *id;
以上是Objective-C语言中id
的实际定义。 Objective-C运行时系统围绕id
和Class
构建。没有什么与NSObject或普通超类有关。
NSObject类
NSObject的是根类,因此不具有父类。它定义了Objective-C对象和对象交互的基本框架 。 它赋予类继承自类的类和实例,它具有作为对象行为的能力并与运行时系统配合运行。
不需要继承任何来自另一个 类的特殊行为的类应该成为NSObject类的子类。 该类的实例至少必须能够在运行时像 Objective-C对象那样运行。继承这个从 开始的能力比使用新的类定义重新创建 要简单得多,也更可靠。
我认为,这是因为它原本是C
不C++
(或其他更严格键入语言)。
NSProxy是可可提供的另一个根类。 –
NSObject包含isa指针,id不包含。看看http://stackoverflow.com/a/19634973/944634 –
什么大声笑? id是一个isa指针。 http://stackoverflow.com/questions/1990695/in-cocoa-how-is-the-id-type-defined – TheAmateurProgrammer