为什么以下代码在#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)要求foo
在 BaseP
. (即见证 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
延期。当你后来符合 SubC
至SubP
,剩下的唯一要求是 SubC
还应符合 BaseP
.好吧,你说SubC
继承自 BaseC
,所以没关系。编译器很高兴,foo
来自 BaseP
扩展最终成为见证人。
关于swift - 调度到 Swift 协议(protocol)扩展,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64113105/