Objective c 什么';声明一个变量之间的区别是什么;id";及;NSObject*“;?

Objective c 什么';声明一个变量之间的区别是什么;id";及;NSObject*“;?,objective-c,Objective C,在Objective-C中,声明变量id与声明变量NSObject*之间有什么区别?对于键入的变量id,您可以向其发送任何已知消息,编译器不会抱怨。对于类型为NSObject*的变量,只能向其发送由NSObject声明的消息(不是任何子类的方法),否则它将生成警告。通常,id是您想要的 进一步说明:所有对象基本上都是id类型。声明静态类型的目的是告诉编译器,“假设这个对象是这个类的一个成员。”因此,如果您向它发送一个类没有声明的消息,编译器可以告诉您,“等等,这个对象不应该得到那个消息!”另外,

在Objective-C中,声明变量
id
与声明变量
NSObject*
之间有什么区别?

对于键入的变量
id
,您可以向其发送任何已知消息,编译器不会抱怨。对于类型为
NSObject*
的变量,只能向其发送由NSObject声明的消息(不是任何子类的方法),否则它将生成警告。通常,
id
是您想要的

进一步说明:所有对象基本上都是
id
类型。声明静态类型的目的是告诉编译器,“假设这个对象是这个类的一个成员。”因此,如果您向它发送一个类没有声明的消息,编译器可以告诉您,“等等,这个对象不应该得到那个消息!”另外,如果两个类有同名但签名不同的方法(即参数或返回类型),它可以猜测您为变量声明的类所指的方法。如果声明为
id
,编译器只会举手告诉您,“好的,我这里没有足够的信息。我随机选择了一个方法签名。”(不过,声明
NSObject*
通常不会有帮助。冲突通常发生在两个更具体的类之间。)

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


另一种声明对象变量的方法类似于“
id
”,意思是“实现
NSObject
协议的任何对象。

根据我对Objective-C的有限理解,并非所有对象都是从NSObject派生的(不像Java中所有对象都是从object派生的)。理论上,您可以有其他根对象。id可以应用于任何非NSObject派生的对象。

我想添加另一个区别。当您将协议添加到
id
时,这不再意味着它将是
NSObject*
类型,而是意味着它将是任何确认该协议的类

因此,例如,此代码不会抛出任何错误,因为
NSObject
的类别
NSDelayedPerforming
具有以下方法:

id testId;
[testId performSelector:@selector(isKindOfClass:) withObject:[NSObject class] afterDelay:.5];
但是,此代码将显示选择器“performSelector:withObject:afterDelay:”的错误
无已知实例方法:

id-testId;
[testId performSelector:@selector(isKindOfClass:)withObject:[NSObject class]afterDelay:.5];

很好的解释,虽然我不太愿意说“一般来说,id就是你想要的”。虽然“id”由于动态类型而非常灵活,但它实际上也不提供任何警告,因此如果调用不受支持的方法,编译时可能捕获的内容将成为运行时问题。静态类型(使用MyClassName*等)如果使用得当,可以使生活变得更加简单,特别是在Xcode中调试时(它可以显示更智能的对象摘要)或者用拼写错误或不完整的选择器捕捉方法调用。我的意思是明确区分id和NSObject*,而不是一般的静态键入。使用id比静态键入NSObject更常见。@simpleBob:因此“任何已知消息”。“@Chuck right,对不起,现在想起来一定太迟了……或者太早了。sproxy和Protocol是类。“类”不是一个类,只是一个可以引用类对象指针的类型。不要把它们混为一谈together@user102008:您可以向类发送消息,使其成为objc世界中的对象。是的,类对象是对象,但它们不属于名为“Class”的类。NSObject包含isa指针,id不包含。请查看
id<NSMutableCopying> testId;
[testId performSelector:@selector(isKindOfClass:) withObject:[NSObject class] afterDelay:.5];