声明variables“id”和“NSObject *”有什么区别?

在Objective-C中,声明variablesid与声明NSObject *什么区别?

使用variablestypes的id ,你可以发送任何已知的消息,编译器不会抱怨。 使用variablestypes的NSObject * ,你只能发送NSObject声明的消息(不是任何子类的方法),否则会产生一个警告。 一般来说, id是你想要的。

进一步解释:所有对象基本上都是idtypes的。 声明静态types的一点是告诉编译器:“假定这个对象是这个类的成员。 所以,如果你发送一个类没有声明的消息,编译器会告诉你,“等等,那个对象不应该得到这个消息!” 另外,如果两个类具有名称相同但签名不同的方法(即参数或返回types),则可以根据您为variables声明的类来猜测您指的是哪个方法。 如果它被声明为id ,那么编译器只会举手告诉你:“好吧,我没有足够的信息,我正在随机select一个方法签名。 (这通常不会通过声明NSObject*来帮助,通常冲突是在两个更具体的类之间)。

id表示“一个对象”, NSObject *表示“ NSObject一个实例或其一个子类”。 Objective-C中有一些不是NSObject的对象(目前在Cocoa中遇到的是NSProxyProtocolClass )。 如果某些代码需要某个特定类的对象,则声明可以帮助编译器检查您是否正确使用它。 如果你真的可以采取“任何对象” – 例如你正在声明一个委托,并将testing与respondsToSelector:调用所有的方法发送 – 你可以使用一个id

另一种声明对象variables的方法就像“ id <NSObject> ”,意思是“任何实现NSObject协议的对象。

从我对Objective-C有限的理解中,并不是所有的对象都是从NSObject派生出来的(不同于所有对象派生自Object的Java)。 你理论上可以有其他的根对象。 ID可以适用于任何这些非NSObject派生的对象。

我想补充一点。 当你添加一个协议到id ,它不再意味着它将是typesNSObject * ,它只是意味着它将是任何类,确认该协议。

所以,例如,这段代码不会抛出任何错误,因为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];