swift - 调度到 Swift 协议(protocol)扩展

标签 swift swift-protocols

为什么以下代码在#2 处打印“BaseP”?

protocol BaseP { func foo() }
extension BaseP { func foo() { print("BaseP") } }
protocol SubP: BaseP {}
extension SubP { func foo() { print("SubP") } }

class C: SubP {}
let subP1: SubP = C()
subP1.foo()   //  #1 prints "SubP", fine.

class BaseC: BaseP {}
class SubC: BaseC, SubP {}
let subP2: SubP = SubC()
subP2.foo()   //  #2 prints "BaseP". why?

    
在这两种情况下,我们都调用 foo()在静态类型为 SubP 的引用上,
引用具有动态类型的对象,该对象是符合 SubP 的类.
即使是静态调度,我认为它仍然应该调用 SubP.foo() .
为什么在#2 调用基本协议(protocol)实现?
另外,为什么从 BaseC 继承?做出改变
(如果在 class SubC 行中,我删除 BaseC 或将其替换为 BaseP
然后它突然打印“SubP”)?

最佳答案

当您调用 subP1.foo()subP2.foo() ,您调用foo满足协议(protocol)要求fooBaseP . (即见证 BaseP.foo 的方法)。 这样的证人只能有一个。
另一个重要的事情是 foo要求不在 SubP 中, 但在 BaseP . 唯一要求SubP是conformer也必须符合BaseP .
subP1 的情况下, C直接符合SubP .解决 SubP 的唯一要求, C还必须符合 BaseP .现在编译器需要确定哪个方法可以见证 foo .有两种方法可用,但一种来自 SubP扩展隐藏 BaseP 中的那个扩展名,所以来自 SubP扩展名被选为见证,所以你看到 SubP打印。
subP2 的情况下,foo 的见证人当你符合 BaseC 时就已经决定了至BaseP .这里只有一个选择——foo来自 BaseC延期。当你后来符合 SubCSubP ,剩下的唯一要求是 SubC还应符合 BaseP .好吧,你说SubC继承自 BaseC ,所以没关系。编译器很高兴,foo来自 BaseP扩展最终成为见证人。

关于swift - 调度到 Swift 协议(protocol)扩展,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64113105/

相关文章:

ios - UIButton 在 collectionView 单元格中不起作用

ios - UILocalNotification 角标(Badge)不会脱落

ios - 如何将视频从 IP 或任何摄像机流式传输到 iOS 应用程序?

swift - 实现泛型协议(protocol)方法但对整个类使用泛型

swift - 制作类型属性并符合 Swift 中的协议(protocol)

ios - 在结构中附加数组 - Swift 2.0

ios - 单击按钮时如何防止查看 View (Swift)

swift - `#selector` 的参数未引用初始化程序或方法

ios - 使用 Rx 扩展模拟一个类

swift - 通过指定类型将 "protocol with associated type"转换为常规协议(protocol)