<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="">This is the reply that I wrote to someone else who wanted a&nbsp;<a href="https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160104/005450.html" class="">private(extension)</a>&nbsp;modifier. Swift's access modifiers align with linker access modifiers and visibility styles: `private` is not exported beyond the translation unit (and can be very aggressively optimized), `internal` is hidden (not exported to the dynamic symbol table) and `public` is exported to the symbol table of the resulting executable. `Private(set)` just means that the setter method is not exported but the getter is.&nbsp;<div class=""><br class=""></div><div class="">So as I said in the other thread, I wouldn't consider that these new modifiers follow the example that private(set) set.</div><div class=""><br class=""></div><div class="">The great thing about using the linker to implement access control is that it can be enforced. The reason internal or private can't be called from outside an executable is that no data about it exists in the final executable As a matter of fact, the symbol itself might not even exist in the fully optimized executable.</div><div class=""><br class=""></div><div class="">I also think that it's fundamentally the same as protected, because nothing prevents you from sharing the logic outside. You can forward the protected call to a public call, which is exactly the same as a public call forwarding to a protected call in terms of encapsulation.</div><div class=""><br class=""></div><div class="">If I can toot my horn, you should consider as an alternative&nbsp;<a href="https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160104/005807.html" class="">better cooperation between the language and the autocomplete/linters</a>. I haven't got around to a new proposal with documentation comments yet but the idea's there.<br class=""><div class=""><div class="">
<br class="Apple-interchange-newline"><span style="color: rgb(0, 0, 0); font-family: 'Lucida Grande'; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; display: inline !important; float: none;" class="">Félix</span>
</div>

<br class=""><div><blockquote type="cite" class=""><div class="">Le 11 janv. 2016 à 19:53:57, Charles Srstka via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; a écrit :</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=""><b class="">Motivation:</b><div class=""><br class=""></div><div class="">The Cocoa frameworks have a long-standing issue regarding methods that are intended as primitives for subclasses to override or for protocol implementers to provide, but which aren’t meant for client code to call directly. Often, the only way to determine that a method shouldn’t be called is to look at the documentation, but that isn’t much of a help when auto-complete suggests such methods, which sometimes look perfectly usable, even tempting, to the naked eye. NSView has a number of them that have come up many a time on mailing lists and support forums in the past, to the extent that Apple has actually created a chart intended to indicate which should be called directly and which shouldn’t:</div><div class=""><br class=""></div><div class=""><a href="https://developer.apple.com/library/mac/releasenotes/UserExperience/RNAutomaticLayout/#//apple_ref/doc/uid/TP40010631-CH1-SW14" class="">https://developer.apple.com/library/mac/releasenotes/UserExperience/RNAutomaticLayout/#//apple_ref/doc/uid/TP40010631-CH1-SW14</a></div><div class=""><br class=""></div><div class="">Clearly advertising things that are not supposed to be actually called is non-ideal in terms of interface.</div><div class=""><br class=""></div><div class=""><b class="">Proposed Solution:</b></div><div class=""><b class=""><br class=""></b></div><div class="">Following the example of private(set), I propose a new access modifier for methods and properties called private(call). A method declared private(call) would behave exactly the same as a private method in almost all circumstances, the one exception being when a subclass attempts to override it (for a class) or a class, struct, or enum implements it (for a protocol). These methods would not be callable by any code outside of the source file that declared the property, and would not show up in code completion.</div><div class=""><br class=""></div><div class="">A similar access modifier, internal(call), would allow the method to be called only by code in the same module, but publicly would be override/implement only.</div><div class=""><br class=""></div><div class=""><b class="">Wait, isn’t this the same as protected?</b></div><div class=""><b class=""><br class=""></b></div><div class="">No. The difference between this and protected is that while protected allows subclasses to access the method and/or property as if it were public, private(call) does *not*. Subclass code is forbidden from accessing the member, exactly as any code from any other class would be. This makes implementation simpler than it would be for protected; private(call) can be treated exactly the same as private for all use cases other than:</div><div class=""><br class=""></div><div class="">1. Displaying the generated “headers” to show the class or protocol’s interface.</div><div class=""><br class=""></div><div class="">2. A method or property declaration in a source code file that either begins with “override” or implements a required member of a protocol.</div><div class=""><br class=""></div><div class="">In all other cases, the compiler can treat private(call) and internal(call) exactly as it would private and internal respectively. It is also more secure than protected, since it cannot be worked around simply by making a subclass of the class in question, and since it reduces the ways a subclass can do something unexpected with the property or method.</div><div class=""><br class=""></div><div class=""><b class="">Alternatives Considered:</b></div><div class=""><b class=""><br class=""></b></div><div class="">In some cases, an exception could be made for Objective-C methods marked OBJC_REQUIRES_SUPER; in such cases, the subclass could be allowed to call super’s implementation, but only from within the override. This could be extended to pure-Swift classes once Swift acquires an equivalent to OBJC_REQUIRES_SUPER. Other than this one exception, even subclasses would not be able to call a method marked private(call). This would, however, complicate the implementation somewhat, and may not be necessary, since any work that the superclass needs to do could be done in a separate method, before calling the private(call) method. There may be some cases where the subclass wants to begin with the return value from the superclass method and modify it slightly, however, in which case this variant may be helpful. It could also possibly be useful in cases where there is a chain of subclasses going several layers down, where each subclass wants to do the work of its own superclass’s implementation before continuing.</div><div class=""><br class=""></div><div class=""><b class="">Summary:</b></div><div class=""><br class=""></div><div class="">All in all, I think this would be a positive contribution to the language. What do you think?</div><div class=""><br class=""></div><div class="">Charles</div>
<img src="https://u2002410.ct.sendgrid.net/wf/open?upn=iRI3beHTe3UxYAHTlV3lA38zIPfHMhyuRzgTmGKV6k4dP69-2B-2B3p0HUUqsoo9m-2FRyRUFOTbBNL8q-2BB7lbxTiNbAAxQyWGnJfKyhz0S4RP7u2bOa38rj7YFStu7-2BvQb6Hf56KZksSL2Eh14lGEKheJos8QRWjN23N1lm9C6hdlh5bUh4dlZBKwN1QG8Jv8jQhVsw6rrj4Pcux-2BY0QqLqXOsw1tDmEtAdZ4JBTKIotQNmM-3D" alt="" width="1" height="1" border="0" style="height:1px !important;width:1px !important;border-width:0 !important;margin-top:0 !important;margin-bottom:0 !important;margin-right:0 !important;margin-left:0 !important;padding-top:0 !important;padding-bottom:0 !important;padding-right:0 !important;padding-left:0 !important;" class="">
</div>
_______________________________________________<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=""></div></blockquote></div><br class=""></div></div></body></html>