使用和不使用协议将选择器发送到id有什么区别?

时间:2014-04-28 15:32:34

标签: ios objective-c compiler-errors clang

怎么可能?

编译错误:

id<NSCoding> response = [[NSObject alloc] init];
id copy = [response copy];

编译成功:

id response = [[NSObject alloc] init];
id copy = [response copy];

编译成功:

id<NSCoding> response = [[NSObject alloc] init];
id copy = [((id)response) copy];

$clang --version
Apple LLVM version 5.1 (clang-503.0.38) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin13.1.0
Thread model: posix

P.S。代码仅用于演示目的,并会引发NSInvalidArgumentException

2 个答案:

答案 0 :(得分:2)

当声明类型为id<SomeProtcol>的变量时,编译器假定您只调用协议中的方法。 copy不是NSCoding协议的方法。

当然,如果变量只是id,那么您可以调用任何已知类/协议中可用的任何方法。

答案 1 :(得分:2)

编译器使用它拥有的任何信息来尝试找出可以使用的方法调用。如果变量只是类型&#34; id&#34;然后编译器对实际对象一无所知,因此无论您发送给对象的方法如何,编译器都必须信任您 - 除非您发送的消息不匹配编译器知道的任何消息。 (编译器可以决定,因为它无法在编译时确定任何消息是有效的,它不允许任何消息,但这会使类型&#34; id&#34;非常无用)。

如果变量具有类型id,则编译器知道此对象支持协议SomeProtocol,但不知道其他任何内容。现在,编译器假设如果您对该对象有更多了解,那么您可以告诉编译器,例如使用NSObject *。由于您没有,编译器将允许发送属于协议的方法