如果我执行以下操作,编译器不会抱怨:
id foo;
[foo retain];
但是,如果我执行以下操作,编译器会抱怨:
id<NSCopying> bar;
[bar retain];
具体来说,它说:
Instance method '-retain' not found (return type defaults to 'id')
这是为什么?我认为id
指向了一个通用的Objective-C对象,我可以将retain
传递给任何Objective-C对象。
注意这是一个警告,而不是一个错误,所以我仍然可以编译代码,它似乎工作。我还注意到我可以执行以下操作来禁止警告:
[(id)bar retain];
但我认为id<NSCopying>
是id
的子类型,因此id
上可以完成的任何内容都可以在id <NSCopying>
上完成...
答案 0 :(得分:2)
您无法将retain
发送到任何 Objective-C对象。 retain
是NSObject协议的一部分。碰巧所有的Cocoa都符合NSObject,但从语言的角度来看,它仍然不是真正的通用(可以定义一个不符合NSObject或继承自NSObject类的类;它只是不是非常有用)。
将id<NSCopying>
声明为“仅允许我在NSCopying协议中发送消息” - 而NSCopying不包含retain
。为了从NSObject协议发送消息,您必须将变量声明为id
(在这种情况下不会发生类型检查),id<NSObject>
(在这种情况下,您只能在NSObject中发送消息)协议)或作为符合NSObject的类的实例。
如果您要将某些内容声明为id<NSCopying>
,则通常需要发送对象copy
而不是retain
,因为这是以这种方式声明的全部内容。如果NSCopying站在这里为你自己的协议,你可以通过这样定义协议本身符合NSObject:
@protocol YourProtocol <NSObject>
如果你真的需要声明一个符合两个协议的变量(这很不寻常,但偶尔会出现),你可以用逗号分隔的协议列表来声明它,比如{{1 }}