<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">Le 9 déc. 2015 à 22:41, Kevin Ballard <<a href="mailto:kevin@sb.org" class="">kevin@sb.org</a>> a écrit :</div><br class="Apple-interchange-newline"><div class="">
<title class=""></title>
<div class=""><div class="">On Wed, Dec 9, 2015, at 01:28 PM, Gwendal Roué wrote:<br class=""></div>
<blockquote type="cite" class=""><div class="">I quite knew about the caveat you’re talking about. This is what had prevented me from shipping this technique in the public API yet. I still need thinking.<br class=""></div>
<div class=""> </div>
<div class="">And my current thinking is that this case is unlikely to happen (in my particular case, at least). Further, I’d rather document against this usage or even cutting off this feature, rather than adding this extra _f function. Talk about a simple API, when the library users needs a PhD in Swift dispatch subtleties to properly validate a poor struct before storing it in the database. That’s not my ambition when I write a library.<br class=""></div>
</blockquote><div class=""> </div>
<div class="">I don't understand. Why does the _f() approach impact library users at all? The only impact it should have on them is showing extra functions in the code completion list, but I seem to recall seeing some reference to doc comment changes being added to Swift to let you influence code completion by indicating that some other function should always be preferred to this one (e.g. so you can mark _f() as saying that users should always call f() instead).<br class=""></div>
<div class=""> </div>
<div class="">The only code that needs to care about the distinction between f() and _f() is in implementations of the protocol P, and I don't see `_f()` as being any worse than `(self as P).f()`. If anything, it's better because it doesn't require the code reader to know whether f() was declared in the protocol (and is therefore subject to overriding).<br class=""></div></div></div></blockquote><div><br class=""></div>I follow all of your points. That _f function is the only reasonable solution in the current state of affairs, I agree.</div><div><br class=""></div><div><div class=""><div class="">Yet, to me, `(self as P).f()`, targeted to the struct writer who has read the doc because he has a feature to write, looks odd, but less dangerous than a public _f function that is available to the struct user who *has not read the manual*. People don’t read the doc unless they have a strong need for it.</div></div></div><div><br class=""></div><div>Like you, when I looked at this solution, I wanted to prefix with an underscore those extra methods: _insert, _update, etc. And exposing public methods with an underscore is so weird, don’t you agree? Again, we’re talking about code that lives in a library that aims at being useful, not an closed-source application with odd but private idiosyncrasies.</div><div><br class=""></div><div>So. My goal is not to spoil this thread. I just want to say that as soon as default implementations were introduced in protocol extensions, for better and for worse, the need for some kind of overriding and `super` was introduced. The current state of the language requires, in all sanity, extra _f functions that are lacking, API-wise.</div><div><br class=""></div><div>The rest of your message is about the fact that I don’t override anything. I know, that’s why I was using "overriding" with quotes. I hope I’ve been more clear in the previous paragraph.</div><div> </div><div><blockquote type="cite" class=""><div class="">
<blockquote type="cite" class=""><div class="">I hope, nevertheless, that I had shown:<br class=""></div>
<div class=""> </div>
<div class="">1. that protocol default implementation can actually be "overriden", even if it is dangerous. If this danger can not be alleviated, then this is a hole in the language, and this hole may well need to be fixed because the inadequate usage I’ve show, should it reveal actually improper, will be discovered by others developers.<br class=""></div>
</blockquote><div class=""> </div>
<div class="">I disagree that this is a hole in the language. You aren't actually overriding anything in your version, you're just providing a method of the same name on the type itself, and according to the Swift language rules if someone calls the method on your type it will prefer your type's version instead of the protocol (this is just due to normal overloading behavior, where your type's method is considered more specific than the protocol and is therefore preferred). And I also think that the current behavior is the correct model; it would be genuinely surprising to me to have methods defined only in extensions actually be overridden by a concrete type when I'm calling the method on the protocol (as opposed to on the concrete type).<br class=""></div>
<div class=""> </div>
<blockquote type="cite" class=""><div class="">2. that there is a quite valid use case for letting adopting types "override" the default implementation of their protocol. The _f extra method is a lacking workaround.<br class=""></div>
</blockquote><div class=""> </div>
<div class="">Well yes, that's kind of the whole point of protocols, isn't it? The problem is you didn't define the method in the protocol. If you want a type to be able to override it, then you have to define it in the protocol. If you don't want it to be able to override it, then you define it in an extension.<br class=""></div>
<div class=""> </div>
<div class="">I'm also a little confused here, because fixing this "hole" would break your code, as you'd no longer be able to get at the default implementation. The only way to recover that behavior, short of inventing brand new syntax, is to use the exact same _f() workaround I just suggested.<br class=""></div>
<div class=""> </div>
<div class="">-Kevin Ballard<br class=""></div>
<div class=""> </div>
<blockquote type="cite" class=""><div class=""><blockquote type="cite" class=""><div class="">Le 9 déc. 2015 à 22:13, Kevin Ballard <<a href="mailto:kevin@sb.org" class="">kevin@sb.org</a>> a écrit :<br class=""></div>
<div class=""> </div>
<div class=""><div class=""><div class="">That is nice, but if someone writes a method that's generic over <T: P> then your "override" won't get called. Seems like it's better to structure it like<br class=""></div>
<div class=""> </div>
<div class=""><span class="font" style="font-family:menlo, consolas, 'courier new', monospace, sans-serif">protocol P {</span><span class="font" style="font-family:menlo, consolas, 'courier new', monospace, sans-serif"></span><br class=""></div>
<div class=""><span class="font" style="font-family:menlo, consolas, 'courier new', monospace, sans-serif"> func f()</span><span class="font" style="font-family:menlo, consolas, 'courier new', monospace, sans-serif"></span><br class=""></div>
<div class=""><span class="font" style="font-family:menlo, consolas, 'courier new', monospace, sans-serif">}</span><span class="font" style="font-family:menlo, consolas, 'courier new', monospace, sans-serif"></span><br class=""></div>
<div class=""><span class="font" style="font-family:menlo, consolas, 'courier new', monospace, sans-serif">extension P {</span><span class="font" style="font-family:menlo, consolas, 'courier new', monospace, sans-serif"></span><br class=""></div>
<div class=""><span class="font" style="font-family:menlo, consolas, 'courier new', monospace, sans-serif"> /// Default implementation for `f`. Calls through to `_f()`.</span><br class=""></div>
<div class=""><span class="font" style="font-family:menlo, consolas, 'courier new', monospace, sans-serif"> func f() { _f() }</span><span class="font" style="font-family:menlo, consolas, 'courier new', monospace, sans-serif"></span><br class=""></div>
<div class=""><span class="font" style="font-family:menlo, consolas, 'courier new', monospace, sans-serif"> /// Helper that provides the base functionality for `f`.</span><br class=""></div>
<div class=""><span class="font" style="font-family:menlo, consolas, 'courier new', monospace, sans-serif"> func _f() { ... }</span><span class="font" style="font-family:menlo, consolas, 'courier new', monospace, sans-serif"></span><br class=""></div>
<div class=""><span class="font" style="font-family:menlo, consolas, 'courier new', monospace, sans-serif">}</span><span class="font" style="font-family:menlo, consolas, 'courier new', monospace, sans-serif"></span><br class=""></div>
<div class=""><span class="font" style="font-family:menlo, consolas, 'courier new', monospace, sans-serif">struct S {</span><span class="font" style="font-family:menlo, consolas, 'courier new', monospace, sans-serif"></span><br class=""></div>
<div class=""><span class="font" style="font-family:menlo, consolas, 'courier new', monospace, sans-serif"> func f() {</span><span class="font" style="font-family:menlo, consolas, 'courier new', monospace, sans-serif"></span><br class=""></div>
<div class=""><span class="font" style="font-family:menlo, consolas, 'courier new', monospace, sans-serif"> ...</span><span class="font" style="font-family:menlo, consolas, 'courier new', monospace, sans-serif"></span><br class=""></div>
<div class=""><span class="font" style="font-family:menlo, consolas, 'courier new', monospace, sans-serif"> _f()</span><span class="font" style="font-family:menlo, consolas, 'courier new', monospace, sans-serif"></span><br class=""></div>
<div class=""><span class="font" style="font-family:menlo, consolas, 'courier new', monospace, sans-serif"> }</span><span class="font" style="font-family:menlo, consolas, 'courier new', monospace, sans-serif"></span><br class=""></div>
<div class=""><span class="font" style="font-family:menlo, consolas, 'courier new', monospace, sans-serif">}</span><br class=""></div>
<div class=""> </div>
<div class="">This way you can write code that's generic over <T: P> (or that takes a P object directly) and it will still call the overrides.<br class=""></div>
<div class=""> </div>
<div class="">-Kevin Ballard<br class=""></div>
<div class=""> </div>
<div class="">On Wed, Dec 9, 2015, at 11:01 AM, Gwendal Roué wrote:<br class=""></div>
<blockquote type="cite" class=""><div class=""> </div>
<div class=""><blockquote type="cite" class=""><div class="">Le 9 déc. 2015 à 19:52, Kevin Ballard via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> a écrit :<br class=""></div>
<div class=""> </div>
<div class=""><span class="font" style="font-family:Helvetica"><span class="size" style="font-size:12px">b) methods defined in protocol extensions by definition can't be overridden already,</span></span><br class=""></div>
</blockquote></div>
<div class=""> </div>
<div class="">Methods defined in protocol extension actually can, sort of, be overridden, and this is very useful:<br class=""></div>
<div class=""> </div>
<div class=""> protocol P { }<br class=""></div>
<div class=""> extension P {<br class=""></div>
<div class=""> func f() { … }<br class=""></div>
<div class=""> }<br class=""></div>
<div class=""> struct S {<br class=""></div>
<div class=""> func f() {<br class=""></div>
<div class=""> ...<br class=""></div>
<div class=""> (self as P).f()<br class=""></div>
<div class=""> …<br class=""></div>
<div class=""> }<br class=""></div>
<div class=""> }<br class=""></div>
<div class=""> </div>
<div class="">I know only one use case for this technique, in the groue/GRDB.swift SQLite wrapper:<br class=""></div>
<div class=""> </div>
<div class="">In this library, a DatabasePersistable protocol provides basic CRUD operations, and a Record class adopts this protocol and "overrides" with the technique above the protocol methods with extra features provided by the class (especially change tracking).<br class=""></div>
<div class=""> </div>
<div class="">The benefits of this architecture are:<br class=""></div>
<div class=""> </div>
<div class="">- You can subclass use the full-featured Record base class, and get CRUD + change tracking for free.<br class=""></div>
<div class="">- The Record subclasses can override the CRUD methods, and add custom code (validation, for example).<br class=""></div>
<div class="">- You can have a custom struct adopt DatabasePersistable, and get CRUD for free.<br class=""></div>
<div class="">- The custom structs that can also "override" the CRUD methods, and add custom code (validation, for example).<br class=""></div>
<div class=""> </div>
<div class="">This is, in my opinion, a very valid use case for this "overriding".<br class=""></div>
<div class="">Gwendal Roué<br class=""></div>
</blockquote><div class=""> </div>
</div>
</div>
</blockquote></div>
</blockquote><div class=""> </div>
</div>
</blockquote></div><br class=""></body></html>