<div style="white-space:pre-wrap">Formal means enforceable by the compiler. File based access control is useful as well but not as a substitute for real data encapsulation.</div><br><div class="gmail_quote"><div dir="ltr">On Mon, Jan 25, 2016 at 8:13 AM Taras Zakharko &lt;<a href="mailto:taras.zakharko@googlemail.com">taras.zakharko@googlemail.com</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word">I disagree with Ilya on his stance on ‘private’. I do understand the argumentation, but the reasoning seems overly formal to me and the classical solution (private visible only within the class) also comes with a number of drawbacks that result in things like friends declarations in C++. It is nice to have relationships between entities explicit, but one can go overboard with the rigidity. <div><br></div><div>However, I also strongly agree with Thorsten that a subclass (but not public) visible modifier has a lot of uses. I would prefer to have four levels of access:</div><div><br></div><div>private (file scope)</div><div>internal (module scope)</div><div>protected (subclass scope)<br><div>public</div><div><br></div><div>Best,</div><div><br></div><div> Taras</div><div><br></div><div><br><div><blockquote type="cite"><div>On 24 Jan 2016, at 09:44, Thorsten Seitz via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:</div><br><div><div style="word-wrap:break-word"><div><span style="white-space:pre-wrap">        </span></div><div><div></div></div></div></div></blockquote></div></div></div></div><div style="word-wrap:break-word"><div><div><div><blockquote type="cite"><div><div style="word-wrap:break-word"><div><div><blockquote type="cite"><div>Am 23.01.2016 um 16:56 schrieb Ilya Belenkiy via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;:</div><br><div><div>I hope that access control can be revisited. It is the number one complaint about Swift that I hear from experienced developers. The current solution came as a complete surprise to every ObjC developer I&#39;ve talked to. The natural expectation was that a strong access control system would be part of a strong type system. I already submitted a pull request with a proposal for this after a lengthy discussion here, but so far it was ignored. I hope that this can be revisited. Even if most people who responded earlier in this list decided that they were happy with the current state, it represents a tiny fraction of people using the language, and at least all the people I talked to strongly disagree but just aren’t on the list.<br><br>Right now access control is file based and not API based. This is much easier to implement but useless to express that certain elements of a class are implementation details that are not meant to be used anywhere else (someone can add more code to the same file and get access to the implementation details without modifying the class). </div></div></blockquote><div><br></div></div></div></div></div></blockquote></div></div></div></div><div style="word-wrap:break-word"><div><div><div><blockquote type="cite"><div><div style="word-wrap:break-word"><div><div><div>I think the file based approach for `private` has advantages because it allows putting several things that have to know each other deeply into the same file (C++ would use friend access for that).<div><br></div></div></div></div></div></div></blockquote></div></div></div></div><div style="word-wrap:break-word"><div><div><div><blockquote type="cite"><div><div style="word-wrap:break-word"><div><div><br><blockquote type="cite"><div><div>It’s also impossible to hide APIs that are meant only for customization points of subclasses.<br></div></div></blockquote><div><br></div></div></div></div></div></blockquote></div></div></div></div><div style="word-wrap:break-word"><div><div><div><blockquote type="cite"><div><div style="word-wrap:break-word"><div><div><div><div>Here I agree. What I am really missing is the ability to declare something „protected“ in a protocol (or class) which is not part of the public API but which I then can use in its default implementation but which has to be provided by implementors of the protocol. </div><div><br></div><div>Example (shortened and simplified to just show the relevant parts):</div><div><br></div><div><font face="Menlo">public protocol StandardGraphTraversal {</font></div><div><font face="Menlo"><span style="white-space:pre-wrap">        </span>// push() and pop() are implementation details and not part of the API</font></div><div><font face="Menlo"><span style="white-space:pre-wrap">        </span>protected func push(vertex: Vertex)</font></div><div><font face="Menlo"><span style="white-space:pre-wrap">        </span>protected func pop() -&gt; Vertex?</font></div><div><font face="Menlo"><br></font></div><div><font face="Menlo"><span style="white-space:pre-wrap">        </span>public func next() -&gt; Vertex?</font></div><div><font face="Menlo">}</font></div><div><font face="Menlo"><br></font></div><div><font face="Menlo">public extension StandardGraphTraversal {</font></div><div><font face="Menlo"><br></font></div><div><font face="Menlo"><span style="white-space:pre-wrap">        </span>// leaving out things like visitor callbacks and coloring the visited vertices</font></div><div><font face="Menlo"><span style="white-space:pre-wrap">        </span>public func next() -&gt; Vertex? {</font></div><div><font face="Menlo"><span style="white-space:pre-wrap">                </span>guard let source = pop() else {<span style="white-space:pre-wrap">                </span>// using pop() here</font></div><div><font face="Menlo"><span style="white-space:pre-wrap">                        </span>return nil</font></div><div><font face="Menlo"><span style="white-space:pre-wrap">                </span>}</font></div><div><font face="Menlo"><span style="white-space:pre-wrap">                </span>for target in graph.neighborsOf(source) {</font></div><div><font face="Menlo"><span style="white-space:pre-wrap">                        </span>if shouldFollowVertex(target) {</font></div><div><font face="Menlo"><span style="white-space:pre-wrap">                                </span>push(vertex)<span style="white-space:pre-wrap">                </span>// using push() here</font></div><div><font face="Menlo"><span style="white-space:pre-wrap">                        </span>}</font></div><div><font face="Menlo"><span style="white-space:pre-wrap">                </span>}</font></div><div><font face="Menlo"><span style="white-space:pre-wrap">        </span>}</font></div><div><font face="Menlo">}</font></div><div><font face="Menlo"><br></font></div><div><font face="Menlo">// supplying the implementation detail: using a queue results in breadth first traversal</font></div><div><font face="Menlo">public struct BreadthFirstTraversal : StandardGraphTraversal {</font></div><div><font face="Menlo"><span style="white-space:pre-wrap">        </span>var queue: Queue&lt;Vertex&gt; = Queue()</font></div><div><font face="Menlo"><br></font></div><div><font face="Menlo"><span style="white-space:pre-wrap">        </span>protected func push(vertex: Vertex) { return queue.push(vertex) }</font></div><div><font face="Menlo"><span style="white-space:pre-wrap">        </span>protected func pop() -&gt; Vertex? { return queue.pop() }</font></div><div><font face="Menlo">}</font></div><div><font face="Menlo"><br></font></div><div><font face="Menlo">// supplying the implementation detail: using a stack results in depth first traversal</font></div><div><font face="Menlo">public struct DepthFirstTraversal : StandardGraphTraversal {</font></div><div><font face="Menlo"><span style="white-space:pre-wrap">        </span>var stack: Stack&lt;Vertex&gt; = Stack()</font></div><div><font face="Menlo"><br></font></div><div><font face="Menlo"><span style="white-space:pre-wrap">        </span>protected func push(vertex: Vertex) { return stack.push(vertex) }</font></div><div><font face="Menlo"><span style="white-space:pre-wrap">        </span>protected func pop() -&gt; Vertex? { return stack.pop() }</font></div><div><font face="Menlo">}</font></div><div><span style="white-space:pre-wrap">        </span></div><div><br></div><div>Currently I cannot express that in Swift and have to make push() and pop() public :-(</div><div><br></div><div>(Allowing `internal` in public protocols would be sufficient in my example but would not help in more general cases where the implementors would have to be provided in another module by the framework user).</div><div><br></div></div></div></div></div></div></blockquote></div></div></div></div><div style="word-wrap:break-word"><div><div><div><blockquote type="cite"><div><div style="word-wrap:break-word"><div><div><br><blockquote type="cite"><div><div>.NET has a good solution that respects the OOP terminology and deals with accessibility in modules and at the API level:<br><a href="https://msdn.microsoft.com/en-us/library/wxh6fsc7.aspx" target="_blank">https://msdn.microsoft.com/en-us/library/wxh6fsc7.aspx</a></div></div></blockquote><div><br></div></div></div></div></div></blockquote></div></div></div></div><div style="word-wrap:break-word"><div><div><div><blockquote type="cite"><div><div style="word-wrap:break-word"><div><div><div>`public` and `internal` seem to be quite the same as in Swift.</div><div>`private` is based on the type instead of the file. I think Swift’s file based `private` is better because it allows to express the same by putting a type into its file alone and allows to create strongly interdependent types by putting them together into the same file.</div><div>`protected` is what I’m missing as well</div><div>`protected internal` seems to be the union of `protected` and `internal`. I think that is not needed and is probably there to allow testing for which Swift has a nicer solution with @testable imports.</div><div><br></div><div>In short the only thing which is missing IMO is `protected`.</div><div><br></div><div>-Thorsten</div></div><br></div></div></div></blockquote></div></div></div></div><div style="word-wrap:break-word"><div><div><div><blockquote type="cite"><div>_______________________________________________<br>swift-evolution mailing list<br><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br></div></blockquote></div></div></div></div></blockquote></div>