在您的扩展的上下文中:
extension P {
func call_foo() { foo() }
func foo() { print("P.foo") }
func call_bar() { bar() }
func bar() { print("P.bar") }
}
C2
不存在,P
是一个协议,方法是静态分派的,尽管bar()
是一个要求P
,它不是由C1
其符合P
so:
let c1: some P = C1()
c1.call_foo() // C1.foo
c1.foo() // C1.foo
c1.call_bar() // P.bar
c1.bar() // P.bar
这是正常的,有趣的是你有:
let someP: some P = C2()
someP.call_foo() // C1.foo
someP.foo() // C1.foo
someP.call_bar() // P.bar
someP.bar() // P.bar
这意味着如果你只有一个参考some P
,子类C2
of C1
其行为与它的超类完全相同:call_bar()
calls P.bar()
因为C1
不实施bar()
现在让我们看看如果你实施会发生什么bar()
in C1
:
class C1: P {
func foo() { print("C1.foo") }
func bar() { print("C1.bar") }
}
class C2: C1 {
override func bar() { print("C2.bar") }
}
如果我们使用引用C1
using some P
:
let c1: some P = C1()
c1.call_foo() // C1.foo
c1.foo() // C1.foo
c1.call_bar() // C1.bar
c1.bar() // C1.bar
now in call_bar()
编译器knows它必须使用C1.bar()
所以参考C2
using some P
:
let someP: some P = C2()
someP.call_foo() // C1.foo
someP.foo() // C1.foo
someP.call_bar() // C2.bar
someP.bar() // C2.bar
子类C2
其行为方式仍然与它的超类相同C1
它的实施bar()
被叫了。 (而且我觉得有点令人安心的 https://en.wikipedia.org/wiki/Liskov_substitution_principle当子类表现得像它们的父类时)。
现在让我们检查原始片段:
let c = C2()
c.call_foo() // C1.foo
c.foo() // C1.foo
c.call_bar() // C2.bar
c.bar() // C2.bar
有用 !