Please consider the following Swift 5 code:
protocol P: class {
func call_foo()
func foo()
func call_bar()
func bar()
}
extension P {
func call_foo() { foo() }
func foo() { print("P.foo") }
func call_bar() { bar() }
func bar() { print("P.bar") }
}
class C1: P {
func foo() { print("C1.foo") }
}
class C2: C1 {
func bar() { print("C2.bar") }
}
let c = C2()
c.call_foo() // C1.foo
c.foo() // C1.foo
c.call_bar() // P.bar
c.bar() // C2.bar
If the foo() call in P.call_foo() gets dynamically dispatched to C1.foo(), then why the bar() call in P.call_bar() does not get dynamically dispatched to C2.bar()?
The only difference is that foo() is overridden directly in the class that conforms to P, and bar() is only overridden in a subclass. Why does that make a difference?
Given that bar() is a protocol requirement, shouldn't all calls to it always get dynamically dispatched?
In the context of your extension:
C2does not exist,Pis a protocol, and methods are dispatched statically, and althoughbar()is a requirements ofP, it is not implemented byC1which has the conformance toPso:and that is normal, and interestingly you have:
Meaning that if you only have a reference to
some P, the subclassC2ofC1behaves exactly as it's superclass:call_bar()callsP.bar()becauseC1does not implementbar()now let's look at what happens if you implement
bar()inC1:If we use a reference to
C1usingsome P:now in
call_bar()the compiler knows it has to useC1.bar()so with a reference toC2usingsome P:The subclass
C2still behaves the same way as it's superclassC1and it's implementation ofbar()get's called. (And I find it somewhat reassuring when sublasses behave as their parent).now let's check the original snippet :
it work's !