我最近一直在学习如何在Objective-C中使用协议(使用Apple的官方指南),而且我一直无法理解我认为不一致的内容。在文件中说明了 -
通过在属性上指定所需的协议一致性,如果尝试将属性设置为不符合协议的对象,则会收到编译器警告,即使基本属性类类型是通用的。 / p>
所以我通过创建一个名为' XYZFakeProtocol'的协议来测试它。还有一个名为' XYZPerson'这不符合这个协议。然后我尝试初始化一个泛型类变量,该变量应符合XYZFakeProtocol,如下所示 -
id <XYZFakeProtocol> speakingPerson = [[XYZPerson alloc] init];
正如所料,XCode标记了错误 -
初始化&#39; __强ID
<
XYZFakeProtocol&gt;&#39;表达不兼容的类型&#39; XYZPerson *&#39;
然而,当我做同样的事情,而是使用工厂方法而不是手动分配和初始化实例时,错误不会出现。我使用的代码,工厂方法是&#39; person:&#39; -
id <XYZFakeProtocol> speakingPerson = [XYZPerson person];
没有标记错误,特别是有问题的是,当我调用协议中指定的方法时,也不会出现编译器错误,即使该方法实际上不在不符合的类中 - 这会导致程序崩溃。 / p>
这是Xcode的一个问题,或者这是使用工厂方法的预期和正确的结果,如果是这样,可以向我解释这背后的推理,以便我可以理解如何最好地避免它我正在编写一个真实的应用程序?
作为参考,如果我创建一个XYZPerson对象并将其分配给XYZPerson变量,Xcode正确地标记该类不符合协议的错误,然后将该变量分配给泛型类型变量,无论该实例是否使用工厂方法创建或手动初始化 -
XYZPerson *helloPerson = [XYZPerson person];
XYZPerson *helloPerson2 = [[XYZPerson alloc] init];
id <XYZFakeProtocol> speakingPerson = helloPerson;
speakingPerson = helloPerson2;
感谢。
答案 0 :(得分:0)
这取决于您的XYZPerson类的定义方式。如果person
返回id
,则类型检查器会将其视为与任何对象类型兼容。如果person
返回instancetype
,您将收到有关协议一致性的错误。
答案 1 :(得分:0)
假设您已声明为:
,这是安全的+ (id)person;
将其更改为:
+ (instancetype)person;
id
表示任何类型,因此编译器不知道返回的对象是否将实现协议。 instancetype
表示该类型的实例,因此编译器确实知道。
instancetype
是一个相对较新的补充,因此编译器很乐意为init
方法引用它。然而,它不愿意为工厂方法这样做。