为什么添加协议(到 id)会导致语义问题



假设我有一个像这样的琐碎类:

@interface ABPair : NSObject
@property id key;
@property id value;
- (void) printSize;
@end
@implementation ABPair
- (void) printSize {
    NSLog(@"the size of your key is: %@", NSStringFromSize([self.key sizeWithAttributes: nil]));
}
@end

这将编译时没有警告(在 Xcode 5 中),并成功运行,并打印合理的值。

但是,如果我进行了以下更改:

@property id<NSCopying> key;

然后我得到两个编译器错误:

  • ARC 语义问题:选择器"sizeWithAttributes:"没有已知的实例方法。
  • 语义问题:将"id"传递给不兼容类型"NSSize"(又名"结构CGSize")的参数

为什么当我完全没有提供有关类型的信息时,编译器能够识别正确的方法(在 NSString 上),但当我说对象必须是该类符合的协议时,编译器无法识别该方法?

id key声明了一个"通用"的Objective-C变量。它可以指向任何对象,编译器接受发送给它的任何消息。如果使用 ARC 进行编译,则只需要知道消息签名到编译器(从任何类)。

id<myprotocol> key专门声明指向符合该协议的对象的指针。编译器仅接受来自<myprotocol>协议(或<myprotocol>继承的其他协议)的消息。

最新更新