您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

调用Swift协议扩展方法代替在子类中实现的方法

调用Swift协议扩展方法代替在子类中实现的方法

这就是协议当前调度方法的方式。

协议见证表(有关更多信息,请参见WWDC谈话)用于在协议类型的实例上被调用时动态地调度到协议要求的实现。实际上,这只是功能实现的清单,以针对给定的符合类型调用协议的每种要求。

声明其对协议一致性的每种类型都有其自己的协议见证表。您会注意到,我说的是“说明其一致性”,而不仅仅是“符合”。BaseClass获得自己的协议见证表以符合要求MyProtocol。但是,SubClass没有 获得自己的表来符合MyProtocol–相反,它仅依赖于BaseClass。如果将: MyProtocol下移到的定义SubClass,它将具有自己的PWT。

因此,我们仅需考虑的是PWT的BaseClass外观。那么,它不会为任何的协议要求提供一个实现methodA()methodB()-因此它依赖于该协议扩展的实现。这意味着BaseClass符合的PWTMyProtocol仅包含到扩展方法的映射。

因此,当methodB()调用extension 方法并将其发出到时methodA(),它会通过PWT动态分派该调用(因为它是在协议类型的实例上调用,即self)。因此,当SubClass实例发生这种情况时,我们将进行BaseClassPWT。因此methodA(),无论是否SubClass提供扩展实现,我们最终都会调用的扩展实现。

现在让我们考虑的PWT JustClass。它提供的实现methodA(),因此,其对符合PWT MyProtocol具有 实施作为映射methodA(),以及对于扩展实现methodB()。因此,当methodA()通过其PWT动态调度时,我们最终实现了

正如我在本问答中所提到的,子类的这种行为没有为其超类所遵循的协议获取自己的PWT确实有些令人惊讶,并且已被记录为bug。正如Swift团队成员Jordan Rose在错误报告的评论中所说的那样,其背后的原因是

[…]子类无法提供新成员来满足一致性要求。这很重要,因为可以将协议添加一个模块中的基类,而可以将其添加到另一个模块中。

因此,如果这是行为,那么已经编译的子类将缺少事实之后在另一个模块中添加的超类一致性中的任何PWT,这将是有问题的。

正如其他人已经说过的,这种情况下的一种解决方案是BaseClass提供自己的实现methodA()。现在,此方法将位于BaseClass的PWT中,而不是扩展方法中。

尽管当然,因为我们在这里处理 ,所以它不只是BaseClass‘列出方法的实现- 而是一个笨拙的东西,然后通过该类动态分配vtable(类实现该机制的机制多态性)。因此,对于一个SubClass实例,我们最终将调用其的覆盖methodA()

Swift 2022/1/1 18:17:23 有454人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶