为什么在我们可以使用NSObject时使用id?

The*_*mer 37 polymorphism cocoa types class objective-c

我知道当我们想要创建一个未知值对象时,我们使用id.但是,我很好奇为什么Apple选择id在运行时决定它的值,当每个对象都是NSObject的子类时.所以id delegate我们可以使用而NSObject *delegate 不是有人知道为什么吗?谢谢.

jus*_*tin 39

id擦除类型,它相当于说"此对象响应翻译可见的任何选择器".当然,当你删除类型时(以及当你对它们进行类型化时),你有责任确保你的程序是正确的.

如果类型是NSObject,那么如果选择器没有在NSObject的接口或它采用的协议中声明,编译器会说"NSObject可能不响应选择器 ".在这种情况下,您还可以添加类型转换以将其强制转换为您期望的类型.

使用严格/正确的类型,编译器可以启动并帮助您,这很好,因为ObjC是一种非常动态的语言.

id在使用(或构建)集合类型时特别有用.除非您定义了新的根类型(不从NSObject继承),否则添加对象不会有问题.如果我们将它用作我们的基类(NSObject)之外的其他东西,那么从集合中获取值将需要类型转换.

Objective-C中不支持泛型-你不能,例如,声明NSArrayNSString秒.当没有保留类型安全性时,您可以NSArray使用NSStrings 填充并传递它id以获得更自然的书面样式(la generics).

所以,让我们用一些真实的代码扩展它.

例A

NSString * string = [array objectAtIndex:0]; // << trust me (via id)
return [string length];
-or-
return [[array objectAtIndex:0] length]; // << trust me (via id)
Run Code Online (Sandbox Code Playgroud)

例B

现在让我们说不id可用,我们修复了所有编译器警告,因为这是正确的做法:

NSString * string  = (NSString*)[array objectAtIndex:0]; // << typecast == trust me
return [string length];
-or-
return [(NSString*)[array objectAtIndex:0] length]; // << typecast == trust me
Run Code Online (Sandbox Code Playgroud)

id不会在运行时决定它的值,也不会决定任何NSObject.ObjC对象不执行隐式促销,它们只是在没有正式提升的情况下投射指针.

与您的示例相关,我实际上将我的委托和参数声明为具有协议的NSObjects:

NSObject<MONShapeDelegate>* delegate;
Run Code Online (Sandbox Code Playgroud)


Jas*_*ien 11

每个对象都是NSObject的子类

这是一个不正确的陈述.您可以创建不从NSObject继承的对象.它不是真的推荐,但它是可能的.

NSProxy 是一个例子 - 它不从NSObject继承.

  • 这只是我答案的克隆! (3认同)
  • 抱歉:/我是在没有答案的情况下写的,你抢先一步...没有什么难受的感觉,也不需要投反对票...另外,你没有提到“NSProxy”... (2认同)
  • @beryl:答案的默认显示顺序按投票总数分箱,然后在每一层内随机化.如果您真的想知道确切的发布时间,那么"X小时前回答"附带的工具提示会为您提供时间戳.您还可以点击答案部分顶部的"最旧"选项卡,通过发布日期来订购答案. (2认同)