<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><blockquote type="cite" class="">There are three reasons I like `final`:<br class=""><br class="">1) It echoes the meaning of `final` in a class—“this is the implementation and you cannot provide any other”.<br class=""><br class="">2) Swift’s general slant is towards using virtual dispatch unless it’s forbidden. (Leaving aside cases where the&nbsp;optimizer can prove at compile time what a dynamic dispatch would do.) That’s why we have a `final` keyword&nbsp;instead of a `virtual` keyword. Because of this, it’s not surprising to Swift users that you *can* override some&nbsp;extension methods; rather, the surprise is that you *can’t* override others. (And the *real* surprise is that you can&nbsp;kind-of-but-not-really override them, and Swift doesn’t complain.) I want developers to mark the surprise.<br class=""><br class="">3) Since, as I said, Swift’s slant is towards virtual dispatch, I think that if Swift eventually permits overriding of&nbsp;protocol extension methods, the overridable behavior should be the default, and the current static behavior&nbsp;should be something you request.</blockquote></div><div class=""><br class=""></div><div class="">Well said, Brent. I agree completely with all these points.</div><div class=""><br class=""></div><div class="">#2 is precisely the reason I threw out that strawman proposal to open the discussion. That strawman long since torn down to satisfaction, I’ve updated the subject line.</div><div class=""><br class=""></div><div class="">The details of the solution are tricky, but I like this general approach with “final” (or whatever the right keyword is). It passes the smell test for me.</div><div class=""><br class=""></div><div class="">• • •</div><div class=""><br class=""></div><div class="">I’m not yet sold on @incoherent. What about preserving the current approach: whenever there are two semantically distinct methods with the same name, require the caller to disambiguate at the call site? For example:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo; color: rgb(102, 139, 73);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">&nbsp; &nbsp;&nbsp;</span>//–––&nbsp;Module Foo ———</div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo; min-height: 12px;" class=""><br class=""></div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo; color: rgb(50, 62, 125);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">&nbsp; &nbsp; </span>extension<span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #587ea8" class="">String</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> {</span></div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; &nbsp; &nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #323e7d" class="">final</span> <span style="font-variant-ligatures: no-common-ligatures; color: #323e7d" class="">func</span> flip() {</div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo; color: rgb(102, 139, 73);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>// reverse order of letters</div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; }</div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo; min-height: 12px;" class=""><br class=""></div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo; color: rgb(102, 139, 73);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">&nbsp; &nbsp; </span>//–––&nbsp;Module Bar ———</div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo; min-height: 12px;" class=""><br class=""></div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo; color: rgb(50, 62, 125);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">&nbsp; &nbsp; </span>extension<span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> </span><span style="font-variant-ligatures: no-common-ligatures; color: #587ea8" class="">String</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class=""> {</span></div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; &nbsp; &nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #323e7d" class="">final</span> <span style="font-variant-ligatures: no-common-ligatures; color: #323e7d" class="">func</span> flip() {</div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo; color: rgb(102, 139, 73);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>// turn letters upside down using funny Unicode chars</div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; &nbsp; &nbsp; }</div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; }</div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo; min-height: 12px;" class=""><br class=""></div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo; color: rgb(102, 139, 73);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">&nbsp; &nbsp; </span>//——— Third module ———</div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo; min-height: 12px;" class=""><br class=""></div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #323e7d" class="">import</span> Foo</div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #323e7d" class="">import</span> Bar</div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo; min-height: 12px;" class=""><br class=""></div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo; color: rgb(102, 139, 73);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">&nbsp; &nbsp; </span>// Please ignore the ugly syntax, and just imagine something</div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo; color: rgb(102, 139, 73);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">&nbsp; &nbsp; </span>// prettier with these semantics:</div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo; min-height: 12px;" class=""><br class=""></div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #843e64" class="">"Swift"</span>.Foo::flip() <span style="font-variant-ligatures: no-common-ligatures; color: #668b49" class="">// → "tfiwS"</span></div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; <span style="font-variant-ligatures: no-common-ligatures; color: #843e64" class="">"Swift"</span>.Bar::flip() <span style="font-variant-ligatures: no-common-ligatures; color: #668b49" class="">// → "ʇɟıʍs"</span></div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo; color: rgb(102, 139, 73);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">&nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #843e64" class="">"Swift"</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">.flip() &nbsp; &nbsp; </span>// compiler error: Ambiguous method "flip()"</div></div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo; color: rgb(102, 139, 73);" class=""><span style="color: rgb(0, 0, 0);" class="">&nbsp; &nbsp;&nbsp;</span>// Another imperfect alternative syntax (same semantic intent, though)<span style="font-size: 10.5px;" class="">:</span></div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo; min-height: 12px;" class=""><br class=""></div><div style="margin: 0px; line-height: normal;" class=""><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp;&nbsp;(<span style="font-variant-ligatures: no-common-ligatures; color: #843e64" class="">"Swift"</span> <span style="font-variant-ligatures: no-common-ligatures; color: #323e7d" class="">as</span> <span style="font-variant-ligatures: no-common-ligatures; color: #587ea8" class="">Foo</span>.<span style="font-variant-ligatures: no-common-ligatures; color: #587ea8" class="">String</span>).flip() <span style="font-variant-ligatures: no-common-ligatures; color: #668b49" class="">// → "tfiwS"</span></div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo;" class="">&nbsp; &nbsp; (<span style="font-variant-ligatures: no-common-ligatures; color: #843e64" class="">"Swift"</span> <span style="font-variant-ligatures: no-common-ligatures; color: #323e7d" class="">as</span> <span style="font-variant-ligatures: no-common-ligatures; color: #587ea8" class="">Bar</span>.<span style="font-variant-ligatures: no-common-ligatures; color: #587ea8" class="">String</span>).flip() <span style="font-variant-ligatures: no-common-ligatures; color: #668b49" class="">// → "ʇɟıʍs"</span></div><div style="margin: 0px; font-size: 10.5px; line-height: normal; font-family: Menlo; color: rgb(102, 139, 73);" class=""><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">&nbsp; &nbsp; </span><span style="font-variant-ligatures: no-common-ligatures; color: #843e64" class="">"Swift"</span><span style="font-variant-ligatures: no-common-ligatures; color: #000000" class="">.flip() &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; </span>// compiler error: Ambiguous method "flip()"</div><div class=""><br class=""></div></div></div><div class="">Both <i class="">syntaxes</i>&nbsp;are ugly, but set syntax aside for a moment. I’m asking about that general approach.</div><div class=""><br class=""></div><div class="">This disambiguation requirement would only apply if there is a pair of methods such that:</div><div class=""><br class=""></div><div class="">1. both methods are visible&nbsp;<i class="">at the call site</i>, and</div><div class="">2. neither one is an ancestor of the other in the same virtually dispatched override hierarchy.</div><div class=""><br class=""></div><div class="">Cheers,</div><div class=""><br class=""></div><div class="">Paul</div><div class=""><br class=""></div><br class=""><blockquote type="cite" class="">On Dec 9, 2015, at 6:09 PM, Brent Royal-Gordon via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:<br class=""><br class=""><blockquote type="cite" class="">Any thoughts on instead having to mark the default method implementations as `default`?<br class=""></blockquote><br class="">There are three reasons I like `final`:<br class=""><br class="">1) It echoes the meaning of `final` in a class—“this is the implementation and you cannot provide any other”.<br class=""><br class="">2) Swift’s general slant is towards using virtual dispatch unless it’s forbidden. (Leaving aside cases where the&nbsp;optimizer can prove at compile time what a dynamic dispatch would do.) That’s why we have a `final` keyword&nbsp;instead of a `virtual` keyword. Because of this, it’s not surprising to Swift users that you *can* override some&nbsp;extension methods; rather, the surprise is that you *can’t* override others. (And the *real* surprise is that you can&nbsp;kind-of-but-not-really override them, and Swift doesn’t complain.) I want developers to mark the surprise.<br class=""><br class="">3) Since, as I said, Swift’s slant is towards virtual dispatch, I think that if Swift eventually permits overriding of&nbsp;protocol extension methods, the overridable behavior should be the default, and the current static behavior&nbsp;should be something you request.<br class=""><br class="">But this is not a terribly strong preference; `default` would be alright too. The more important point to me is that&nbsp;the user should acknowledge the weird behavior of shadowing a protocol extension method. In other words, I&nbsp;think the `@incoherent` annotation on the conformance is actually more important than the `final` or `default`&nbsp;keyword on the declaration.<br class=""><br class=""><blockquote type="cite" class="">It still seems strange to me to consider a protocol extension that uses the `final` keyword, because a) protocols&nbsp;have nothing to do with classes and `final` means no subclassing<br class=""></blockquote><br class="">The way I see it, `final` in a class is a way of saying “All instances of this class (including subclasses) must use this&nbsp;implementation and cannot substitute a different one”. Similarly, `final` in a protocol means “All instances&nbsp;conforming to this protocol must use this implementation and cannot substitute a different one”.<br class=""><br class="">That’s why @incoherent is important. It’s basically saying “I know there are final members in this type and I can’t&nbsp;really override them, but I want to shadow them anyway, even though the result is going to be kind of half-assed.” You could even imagine it being applied to superclasses, allowing you to shadow their `final` members in&nbsp;the same way you can shadow protocol extension methods.<br class=""><br class=""><blockquote type="cite" class="">and b) methods defined in protocol extensions by definition can't be overridden already, so the `final` keyword is&nbsp;just sort of like saying "no really, I mean it, you can't do the thing you already can't do!”.<br class=""></blockquote><br class="">That is *exactly* the point of what I’m proposing. Just like the `override` keyword sort of says “no really, I mean it,&nbsp;I want to do the thing I’m doing!"<br class=""><br class="">--&nbsp;<br class="">Brent Royal-Gordon<br class="">Architechies<br class=""><br class="">_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></blockquote><br class=""></body></html>