<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="">I didn’t propose to remove or repurpose the existing “private” access modifier. Instead, I proposed an additional “local” modifier for real data encapsulation. I think that the current “private” modifier is misnamed. It would be much more concise to call it “file internal” or something similar, but it looks like it’s too late to change this now. Both “private” and “local” are useful. One doesn’t have to exclude the other.<div class=""><br class=""></div><div class=""><blockquote type="cite" class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class="">Yes, it does trade formalism for convenience, but I believe that the tradeoff is reasonable. </div></div></blockquote><div class=""><br class=""></div>Both can and should exist in the language. No need for tradeoffs.</div><div class=""><br class=""></div><div class=""><blockquote type="cite" class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class="">You already need to maintain some degree of discipline when writing code (you can’t make the compiler to enforce all conventions for you)</div></div></blockquote><div class=""><br class=""></div>In every other respect, Swift compiler tries to help, except this one. The strong type system and type inference are a big deal. This is a big deal for the same reason.<br class=""><div class=""><div class=""><br class=""></div><div class=""><div class=""><blockquote type="cite" class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class="">I don’t think that its such a big deal to ask people to be careful when modifying a file with a pre-existing type implementation.</div></div></blockquote><br class=""></div><div class="">An intent, clearly spelled out in the property or function declaration, that is enforceable by the compiler will eliminate human errors much more reliably than convention and attempts to be careful. We have ARC and destructors that are automatically called for the same reason.</div><div class=""><br class=""></div><div class=""><blockquote type="cite" class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class="">In the end, your argumentation mainly applies to the case when you have multiple type implementation in the same file. Which is bad style in the first place. </div></div></blockquote><br class=""></div><div class="">This is a matter or opinion. Earlier:</div><div class=""><br class=""></div><div class=""><blockquote type="cite" class="">If one class and one extension per file become a requirement,<br class="">then private will have the same semantics as in C++. It will also<br class="">become very inconvenient to write code because even a small extension<br class="">with 1 method that can fit on one line will require a separate file.</blockquote><br class=""></div><div class="">Which is why this rule “one class per file” is not there.</div><div class=""><br class=""></div><div class=""><blockquote type="cite" class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class="">Once you embrace idea that all declarations in a single file are closely interdependent (this way or another), file-based access control stops being an issue as you present it. </div></div></blockquote><br class=""></div><div class="">It will still be an issue because there is no way to express the author’s intent on whether something is truly private or can be safely shared with closely related code.</div><div class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Jan 25, 2016, at 9:04 AM, Taras Zakharko <<a href="mailto:taras.zakharko@uzh.ch" class="">taras.zakharko@uzh.ch</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">That is true of course, but explicitly modelling complex dependency relationships between scopes can be tedious. If you make private truly private, then you also need concepts such a friends and many some others in order to write efficient code. File- and module-based access offers a decent compromise by allowing you to put interdependent implementations into a single file. Personally, I think that this is an elegant and reasonable solution. Yes, it does trade formalism for convenience, but I believe that the tradeoff is reasonable. You already need to maintain some degree of discipline when writing code (you can’t make the compiler to enforce all conventions for you), and I don’t think that its such a big deal to ask people to be careful when modifying a file with a pre-existing type implementation. In the end, your argumentation mainly applies to the case when you have multiple type implementation in the same file. Which is bad style in the first place. Once you embrace idea that all declarations in a single file are closely interdependent (this way or another), file-based access control stops being an issue as you present it. </div><div class=""><br class=""></div><div class="">Best, </div><div class=""><br class=""></div><div class=""> Taras </div><br class=""><div class=""><blockquote type="cite" class=""><div class="">On 25 Jan 2016, at 14:45, Ilya Belenkiy <<a href="mailto:ilya.belenkiy@gmail.com" class="">ilya.belenkiy@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div style="white-space:pre-wrap" class="">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 class=""><div class="gmail_quote"><div dir="ltr" class="">On Mon, Jan 25, 2016 at 8:13 AM Taras Zakharko <<a href="mailto:taras.zakharko@googlemail.com" class="">taras.zakharko@googlemail.com</a>> wrote:<br class=""></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" class="">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 class=""><br class=""></div><div class="">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 class=""><br class=""></div><div class="">private (file scope)</div><div class="">internal (module scope)</div><div class="">protected (subclass scope)<br class=""><div class="">public</div><div class=""><br class=""></div><div class="">Best,</div><div class=""><br class=""></div><div class=""> Taras</div><div class=""><br class=""></div><div class=""><br class=""><div class=""><blockquote type="cite" class=""><div class="">On 24 Jan 2016, at 09:44, Thorsten Seitz via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>> wrote:</div><br class=""><div class=""><div style="word-wrap:break-word" class=""><div class=""><span style="white-space:pre-wrap" class="">        </span></div><div class=""><div class=""></div></div></div></div></blockquote></div></div></div></div><div style="word-wrap:break-word" class=""><div class=""><div class=""><div class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap:break-word" class=""><div class=""><div class=""><blockquote type="cite" class=""><div class="">Am 23.01.2016 um 16:56 schrieb Ilya Belenkiy via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>>:</div><br class=""><div class=""><div class="">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'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 class=""><br class="">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 class=""><br class=""></div></div></div></div></div></blockquote></div></div></div></div><div style="word-wrap:break-word" class=""><div class=""><div class=""><div class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap:break-word" class=""><div class=""><div class=""><div class="">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 class=""><br class=""></div></div></div></div></div></div></blockquote></div></div></div></div><div style="word-wrap:break-word" class=""><div class=""><div class=""><div class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap:break-word" class=""><div class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div class="">It’s also impossible to hide APIs that are meant only for customization points of subclasses.<br class=""></div></div></blockquote><div class=""><br class=""></div></div></div></div></div></blockquote></div></div></div></div><div style="word-wrap:break-word" class=""><div class=""><div class=""><div class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap:break-word" class=""><div class=""><div class=""><div class=""><div class="">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 class=""><br class=""></div><div class="">Example (shortened and simplified to just show the relevant parts):</div><div class=""><br class=""></div><div class=""><font face="Menlo" class="">public protocol StandardGraphTraversal {</font></div><div class=""><font face="Menlo" class=""><span style="white-space:pre-wrap" class="">        </span>// push() and pop() are implementation details and not part of the API</font></div><div class=""><font face="Menlo" class=""><span style="white-space:pre-wrap" class="">        </span>protected func push(vertex: Vertex)</font></div><div class=""><font face="Menlo" class=""><span style="white-space:pre-wrap" class="">        </span>protected func pop() -> Vertex?</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class=""><span style="white-space:pre-wrap" class="">        </span>public func next() -> Vertex?</font></div><div class=""><font face="Menlo" class="">}</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">public extension StandardGraphTraversal {</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class=""><span style="white-space:pre-wrap" class="">        </span>// leaving out things like visitor callbacks and coloring the visited vertices</font></div><div class=""><font face="Menlo" class=""><span style="white-space:pre-wrap" class="">        </span>public func next() -> Vertex? {</font></div><div class=""><font face="Menlo" class=""><span style="white-space:pre-wrap" class="">                </span>guard let source = pop() else {<span style="white-space:pre-wrap" class="">                </span>// using pop() here</font></div><div class=""><font face="Menlo" class=""><span style="white-space:pre-wrap" class="">                        </span>return nil</font></div><div class=""><font face="Menlo" class=""><span style="white-space:pre-wrap" class="">                </span>}</font></div><div class=""><font face="Menlo" class=""><span style="white-space:pre-wrap" class="">                </span>for target in graph.neighborsOf(source) {</font></div><div class=""><font face="Menlo" class=""><span style="white-space:pre-wrap" class="">                        </span>if shouldFollowVertex(target) {</font></div><div class=""><font face="Menlo" class=""><span style="white-space:pre-wrap" class="">                                </span>push(vertex)<span style="white-space:pre-wrap" class="">                </span>// using push() here</font></div><div class=""><font face="Menlo" class=""><span style="white-space:pre-wrap" class="">                        </span>}</font></div><div class=""><font face="Menlo" class=""><span style="white-space:pre-wrap" class="">                </span>}</font></div><div class=""><font face="Menlo" class=""><span style="white-space:pre-wrap" class="">        </span>}</font></div><div class=""><font face="Menlo" class="">}</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">// supplying the implementation detail: using a queue results in breadth first traversal</font></div><div class=""><font face="Menlo" class="">public struct BreadthFirstTraversal : StandardGraphTraversal {</font></div><div class=""><font face="Menlo" class=""><span style="white-space:pre-wrap" class="">        </span>var queue: Queue<Vertex> = Queue()</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class=""><span style="white-space:pre-wrap" class="">        </span>protected func push(vertex: Vertex) { return queue.push(vertex) }</font></div><div class=""><font face="Menlo" class=""><span style="white-space:pre-wrap" class="">        </span>protected func pop() -> Vertex? { return queue.pop() }</font></div><div class=""><font face="Menlo" class="">}</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">// supplying the implementation detail: using a stack results in depth first traversal</font></div><div class=""><font face="Menlo" class="">public struct DepthFirstTraversal : StandardGraphTraversal {</font></div><div class=""><font face="Menlo" class=""><span style="white-space:pre-wrap" class="">        </span>var stack: Stack<Vertex> = Stack()</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class=""><span style="white-space:pre-wrap" class="">        </span>protected func push(vertex: Vertex) { return stack.push(vertex) }</font></div><div class=""><font face="Menlo" class=""><span style="white-space:pre-wrap" class="">        </span>protected func pop() -> Vertex? { return stack.pop() }</font></div><div class=""><font face="Menlo" class="">}</font></div><div class=""><span style="white-space:pre-wrap" class="">        </span></div><div class=""><br class=""></div><div class="">Currently I cannot express that in Swift and have to make push() and pop() public :-(</div><div class=""><br class=""></div><div class="">(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 class=""><br class=""></div></div></div></div></div></div></blockquote></div></div></div></div><div style="word-wrap:break-word" class=""><div class=""><div class=""><div class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap:break-word" class=""><div class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div class="">.NET has a good solution that respects the OOP terminology and deals with accessibility in modules and at the API level:<br class=""><a href="https://msdn.microsoft.com/en-us/library/wxh6fsc7.aspx" target="_blank" class="">https://msdn.microsoft.com/en-us/library/wxh6fsc7.aspx</a></div></div></blockquote><div class=""><br class=""></div></div></div></div></div></blockquote></div></div></div></div><div style="word-wrap:break-word" class=""><div class=""><div class=""><div class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap:break-word" class=""><div class=""><div class=""><div class="">`public` and `internal` seem to be quite the same as in Swift.</div><div class="">`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 class="">`protected` is what I’m missing as well</div><div class="">`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 class=""><br class=""></div><div class="">In short the only thing which is missing IMO is `protected`.</div><div class=""><br class=""></div><div class="">-Thorsten</div></div><br class=""></div></div></div></blockquote></div></div></div></div><div style="word-wrap:break-word" class=""><div class=""><div class=""><div class=""><blockquote type="cite" class=""><div class="">_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></div></blockquote></div></div></div></div></blockquote></div>
</div></blockquote></div><br class=""></div></div></blockquote></div><br class=""></div></div></div></div></body></html>