imr*_*mre 5 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?
Run Code Online (Sandbox Code Playgroud)
在这两种情况下,我们调用foo()静态类型为 的SubP引用,引用具有动态类型的对象,该对象是符合 的类SubP。即使它是静态调度,我认为它仍然应该调用SubP.foo(). 为什么在#2 处调用基本协议实现?
另外,为什么继承 fromBaseC会有所不同(如果class SubC在行中我将BaseC其删除或替换为BaseP,那么它会突然打印“SubP”)?
当您调用subP1.foo()或时subP2.foo(),您正在调用满足中的foo协议要求的。(即见证的方法)。这样的证人只能有一名。fooBaseP BaseP.foo
另一件重要的事情是,foo要求不是在SubP,而是在BaseP。的唯一要求SubP是符合者也必须符合BaseP。
的情况下subP1,C直接符合SubP。要解决 的唯一要求SubP,C还必须符合BaseP。现在编译器需要确定哪个方法可以见证foo。有两种方法可用,但是来自SubP扩展程序的方法隐藏了来自扩展BaseP程序的方法,因此选择来自SubP扩展程序的方法作为见证人,因此您可以看到SubP打印的内容。
在这种情况下,当你遵守时,subP2见证人foo就已经决定了。在这里,只有一种选择 -来自扩展。当你以后遵守时,剩下的唯一要求就是也应该遵守。嗯,你说继承自,所以没问题。编译器很高兴,并且从扩展中最终成为见证者。BaseCBasePfooBaseCSubCSubPSubCBasePSubCBaseCfooBaseP
| 归档时间: |
|
| 查看次数: |
51 次 |
| 最近记录: |