<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 4 mars 2016 à 21:28, Wallacy &lt;<a href="mailto:wallacyf@gmail.com" class="">wallacyf@gmail.com</a>&gt; a écrit :</div><br class="Apple-interchange-newline"><div class=""><div class="">This should be resolved when<span class="Apple-converted-space">&nbsp;</span><a href="http://article.gmane.org/gmane.comp.lang.swift.evolution/3082" class="">PwS<span class="Apple-converted-space">&nbsp;</span></a>(Protocol with Storage) get alive:<br class=""></div><div class=""><br class=""></div></div></blockquote><blockquote type="cite" class="">[…]<br class=""></blockquote><blockquote type="cite" class=""><div class=""><div class=""><br class=""></div><div class="">This is another proposal, but the idea is improve the current protocol model instead to create another type just because a single skill.</div></div></blockquote><br class=""></div><div>Yes. But I wanted to talk about visibility, not about storage. Quoting myself:</div><div><br class=""></div><div><div class="">The problem with protocols is that the implementation detail referenceRow has to be public (when it should remain an implementation detail), and that the conforming types must provide it (when they should not even know about its existence):<br class=""></div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>// Framework land<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>public abstract class DatabaseRecord {<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>// DatabaseRow initializer<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>public required init(row: DatabaseRow) {<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>referenceRow = row<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>}<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>// The table name<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>public abstract class func databaseTableName() -&gt; String<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>// What should be stored in the database<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>public abstract var persistedRow: DatabaseRow<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>// True if record has been changed since last fetch<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>public var hasChanges: Bool {&nbsp;<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>// return complex computation based on referenceRow and persistedRow<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>}<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>// Hidden implementation detail<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>internal var referenceRow: DatabaseRow<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>}<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>// User land<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>class Person : DatabaseRecord {<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>var name: String<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>class func databaseTableName() -&gt; String { return "persons" }<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>init(row: DatabaseRow) {<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>name = row["name"]<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>super.init(row)<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>}<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>var persistedRow: DatabaseRow { return Row("name": name) }<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>}<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let person = Person(row: …)<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>person.name<span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>// "foo"<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>person.hasChanges<span class="Apple-tab-span" style="white-space: pre;">        </span>// false<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>person.name = "bar"<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>person.hasChanges<span class="Apple-tab-span" style="white-space: pre;">        </span>// true<br class=""><br class=""><br class="">How do we express this with protocols?<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>// Framework land<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>public protocol DatabaseRecord {<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>var referenceRow: DatabaseRow { get set }<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>var persistedRow: DatabaseRow { get }<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>static func databaseTableName() -&gt; String<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>init(row: DatabaseRow)<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>}<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>extension DatabaseRecord {<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>public var hasChanges: Bool {&nbsp;<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>// return complex computation based on referenceRow and persistedRow<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>}<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>}<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>// User land<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>class Person: DatabaseRecord {<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>var referenceRow: DatabaseRow<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>var name: String<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>init(row: DatabaseRow) {<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>name = row["name"]<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>super.init(row)<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>}<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>class func databaseTableName() -&gt; String { return « persons" }<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>var persistedRow: DatabaseRow { return Row("name": name) }<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>}<br class=""><br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>let person = Person(row: …)<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>person.name<span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="Apple-tab-span" style="white-space: pre;">        </span>// "foo"<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>person.hasChanges<span class="Apple-tab-span" style="white-space: pre;">        </span>// false<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>person.name = "bar"<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>person.hasChanges<span class="Apple-tab-span" style="white-space: pre;">        </span>// true<br class=""><span class="Apple-tab-span" style="white-space: pre;">        </span>person.referenceRow = …<span class="Apple-tab-span" style="white-space: pre;">        </span>// messed up internal state<br class=""></div><div class=""><br class=""></div></div></body></html>