Objective-C运行时:声明类型为Class(objc_class)的变量符合协议意味着什么?

Rei*_*ain 8 objective-c objective-c-runtime

Class bah = [NSString class];

id object = [bah new];
Run Code Online (Sandbox Code Playgroud)

编译完全没有问题.

Class<NSSecureCoding> bah = [NSString class];

id object = [bah new];
Run Code Online (Sandbox Code Playgroud)

返回错误"选择器'new'没有已知的类方法".

为什么第一个实例理解它可以调用+newNSObject上定义的方法但第二个实例不能?

Gav*_*vin 5

根据Apple的文档:

协议不能用于键入类对象.只有实例可以静态类型化为协议,就像只有实例可以静态类型化为类一样.(但是,在运行时,类和实例都会响应conformsToProtocol:消息.)

这是来自旧的文档,但没有任何说它已经改变了.但假设它仍然有效,基于此,你不应该做你正在做的事情.实例NSString可能符合该协议,但您不应该说该NSString Class对象符合该协议.

至于它为什么会给你错误,我相信这是因为当你指定协议时,它会报告不在该协议中的方法的错误.例如,以下内容给出了错误:

Class<NSSecureCoding> bah = [NSString class];
id object = [bah class];
Run Code Online (Sandbox Code Playgroud)

但是下面将编译(尽管它给出了一个警告,它class是一个实例方法,而不是一个类方法):

Class<NSObject> bah = [NSString class];
id object = [bah class];
Run Code Online (Sandbox Code Playgroud)

你也会注意到协议中new没有定义NSObject,只在NSObject课堂上定义.

因此,当您指定时Class,编译器似乎执行与您指定时类似的操作id,因为它不知道确切的类型,因此它将允许您从任何已知类型调用方法.但是当你向它添加协议时,它只会让你调用该协议的方法.

如果您想确保在使用时分配的任何内容bah符合特定协议Class,您可以使用以下内容:

if ([bah conformsToProtocol:@protocol(NSSecureCoding)])
Run Code Online (Sandbox Code Playgroud)

  • 这是您所指的遗留文档的链接:[面向对象的编程和Objective-C编程语言1.0](https://developer.apple.com/legacy/library/documentation/Cocoa/Conceptual/OOPandObjC1 /OOPandObjC1.pdf),第62页.(我的答案差不多完了:-) (3认同)
  • 而btw,`Class <AnyProcol> = [NSString class]`编译时没有警告*any*协议. - 另见http://lists.cs.uiuc.edu/pipermail/llvmbugs/2013-March/027464.html. (2认同)