Dispatch in Protocols

According to what I understood about dispatch in protocols here (correct me if I am wrong) is..... swift bypasses the greet method declared in struct when greeter.greet method is called first.This is because the extension protocol gets replaced inside the protocol witness table.
In second function call, it prints bye rather than Tshcuus. Clearly, leave method from extension is printed. I read the explanation why does this happen but I am not confident much if I understand this completely.
Kindly Explain briefly.:slightly_smiling_face:

Because the variable is declared as Greetable, and leave is not a requirement for the protocol.
Maybe it helps to think of the situation this way:
The compiler knows that the object — no matter what type it actually has — has a greet-method; either a custom one, or the default implementation from the protocol as a fallback.

For leave on the other hand, it is only clear that there is an implementation from the protocol, so that is called.

Wouldn't it be possible to call the custom implementation anyways?
Technically, probably yes... but it would be more brittle:
Methods can be declared in many different places (and modules). For example, what should happen if there is a second leave supplied by another protocol the type conforms to? Should that also be preferred over the method from the "right" protocol, which hopefully designed its methods so that they make sense in combination?

1 Like

The difference here is whether the method is declared in the main body of the protocol or not (the actual protocol Greetable declaration. Members listed there (such as greet) are called "requirements", and you can provide implementations for them in extensions, which are known as "default implementations."

Somewhat confusingly, you can also define other members in protocol extensions. I'm not sure there's a super solid consensus around what to call these members, though the common terminology seems to be "extension methods" or "extension members."

I say "confusingly" because as you've noted, despite the fact that Greetable.greet and Greetable.leave look very similar at the point where they are implemented, their behavior can differ significantly when being called.

When a type conforms to a protocol, it must provide implementations for all of the protocol requirements, which establishes a correspondence between, e.g., GermanGreeter.greet and the Greeter.greet requirement. Thus, when you have a value of type GermanGreeter and store it in a variable of type Greetable, that correspondence is maintained and allows the Greetable variable to call the GermanGreeter.greet implementation when you call greeter.greet() above.

However, since leave is not a protocol requirement, no such correspondence is established between Greetable.leave and GermanGreeter.leave—as far as Swift is concerned, these are two completely different methods that happen to share the same name (the technical term for this is "shadowing"). Thus, when you have a variable of type Greetable, the compiler can only find the Greetable.leave declaration, since GermanGreeter.leave is completely unrelated. The correspondence that was maintained between GermanGreeter.greet and Greetable.greet above doesn't apply, since Greetable.leave isn't a requirement.

4 Likes