声明变量“id”和“NSObject *”有什么区别?
使用变量类型id
,您可以发送任何已知消息并且编译器不会发出抱怨。使用变量NSObject *
,您只能发送由NSObject声明的消息(不是任何子类的方法),否则它将生成警告。一般来说,id
是你想要的。
进一步说明:所有物体基本上都是id
型。声明一个静态类型的意义是告诉编译器,“假设这个对象是这个类的成员。”所以如果你给它发送一个类没有声明的消息,编译器会告诉你,“等等,那个对象不应该得到那个消息!”另外,如果两个类具有名称相同但签名不同的方法(即参数或返回类型),则它可以猜测您为变量声明的类所指的方法。如果它被声明为id
,编译器就会举起手来告诉你:“好的,我没有足够的信息,我随机选择了一个方法签名。” (这通常不会被通过声明NSObject*
帮助,虽然,通常的冲突是两个具体的类之间。)
很好的解释,尽管我毫不犹豫地说,“一般来说,id是你想要的”。虽然“id”由于动态类型而非常灵活,但它也不提供任何警告,因此如果调用不支持的方法,那么在编译时可能发生的问题将成为运行时问题。静态类型(使用MyClassName *等)明智地使用可以使生活变得更简单,特别是在Xcode中进行调试时(它可以显示更智能的对象摘要)或使用拼写错误或不完整的选择器捕获方法调用。 – 2009-06-25 07:28:16
我打算绘制的区别是在id和NSObject *之间,而不是一般的静态类型。你希望使用id而不是静态类型作为NSObject更常见。 – Chuck 2009-06-25 14:57:19
id
指“一个对象”,NSObject *
装置“的NSObject
或其子类之一的实例”。 Objective-C中有些对象不是NSObject
(目前在Cocoa中遇到的对象是NSProxy
,Protocol
和Class
)。如果某些代码需要某个特定类的对象,那么声明可以帮助编译器检查您是否正确使用它。如果你真的可以采取“任何对象” - 例如你正在宣布一个委托,并将通过respondsToSelector:
调用来测试所有的方法发送 - 你可以使用id
。
另一种方式来声明对象变量是如“id <NSObject>
”,意思是“它实现任何对象NSObject
协议。
从我有限Objective-C的,不是所有的目标都从NSObject的衍生的理解(不像Java的所有的对象都派生自object),理论上可以有其他的根对象。ID可以适用于任何那些非NSObject的派生的对象的。
我想补充的另一个区别。当你添加一个协议id
,它不再意味着它将是NSObject *
类型,它只是意味着它将是任何分类这证实了该协议。
因此,举例来说,该代码不会抛出任何错误,因为NSObject
的类别NSDelayedPerforming
有一个方法:
id testId;
[testId performSelector:@selector(isKindOfClass:) withObject:[NSObject class] afterDelay:.5];
然而,该代码会显示错误No known instance method for selector "performSelector:withObject:afterDelay:"
:
id<NSMutableCopying> testId;
[testId performSelector:@selector(isKindOfClass:) withObject:[NSObject class] afterDelay:.5];
NSObject包含isa指针,id不包含。看看http://stackoverflow.com/a/19634973/944634 – 2013-10-28 13:05:06