[swift-evolution] Simplifying Access Using 'Hidden'

Xiaodi Wu xiaodi.wu at gmail.com
Mon Feb 13 14:16:50 CST 2017


Hasn't "hidden" already been discussed? I could swear that it was already
pitched and feedback given.

In any case there's an ongoing discussion in another thread about removing
new private; it seems distinctly poor form to abandon that and propose
doing the exact opposite (removing old private) in a new thread.


On Mon, Feb 13, 2017 at 08:06 Jonathan Hull via swift-evolution <
swift-evolution at swift.org> wrote:

> I wanted to propose a second simplification to the access system which
> would have several benefits:
>
>         • It would remove ‘fileprivate’
>         • It would allow extensions to be in their own files
>         • It would serve the needs of ‘protected’ without the
> complications involved in that
>         • It would serve some of the needs of submodules (but also work
> together with them really nicely when we have both)
>         • It would allow protocols to have something similar to private
> methods, which are not exposed to callers of the protocol, but still
> required for conformance
>
>
> My proposal is to add a ‘hidden’ access modifier which would act as a
> separate AXIS as opposed to a new level.  Thus, it could be combined with
> any of the other modifiers (e.g. 'public hidden var’).  The ‘fileprivate’
> level would be removed.
>
> Anything which is marked hidden is not visible outside of the file it is
> defined in.  That visibility can be explicitly restored on a per file basis
> (but only within the defined access level). Take a look at the following:
>
>         //File: MyStruct.swift
>
>         struct MyStruct {
>                 var a:Int
>                 hidden var b:Int
>         }
>
>         extension MyStruct {
>                 var biggest:Int {return max(a,b)} //We can still see ‘b’
> because it is only hidden outside the file
>         }
>
> Here we see that ‘b’ behaves very similarly to the way fileprivate works
> now.  ‘b’ is technically still internal, but it is hidden and thus can’t be
> seen outside the file.  The difference is that instead of being forced to
> add all of our extensions in the same file, we can organize them however we
> prefer.
>
>         //In another file
>         import hidden MyStruct //This exposes all ‘hidden’ items from the
> file MyStruct to this file
>
>         extension MyStruct {
>                 var c:Int {return a + b} //We can see ‘b’ because of the
> ‘import hidden’ statement
>         }
>
>
> Notice how the intent has been shown here.  ‘b’ is marked ‘internal’,
> which means we know that no one can see ‘b’ outside of the module.  In
> addition ‘b’ is marked ‘hidden’, which means that the author is saying that
> this should only really be accessed from extensions, subclasses, or types
> which would be called friends in other languages.  The actual guarantee is
> still ‘internal’, but a caller does have to explicitly request the access
> by typing ‘import hidden’, which will stop accidental/casual misuse.
> (If/when we get submodules, then we can make tighter guarantees)
>
> This also allows a class to “hide the ejection seat levers” from its
> callers, while still allowing access for subclasses and extensions (i.e. it
> does most of what ‘protected’ would do, but with swift’s simpler file-based
> access model)
>
> The same is true of protocols.  There are often methods I have to include
> on protocols which are needed by the default implementations, but NEVER
> meant to be called directly by callers of the protocol.  If vars/methods of
> a protocol are marked hidden, then they would be hidden from callers of the
> protocol outside the file.  They are still required for conformance,
> however*.
>
>         protocol MyProtocol {
>                 var a:Int
>                 hidden var b:Int  //Conformers still need to provide this,
> but callers can’t see it
>         }
>
>         extension MyProtocol {
>                 func doSomethingBasedOnB() {
>                         //The extension can see b in the same file, but
> callers in other files won’t have access to ‘b’ directly
>                 }
>         }
>
> I think all of this works really well with Swift’s goal of progressive
> disclosure.  Users of protocols/classes/etc… are not exposed to the
> internals necessary for extension (e.g. it won’t come up in autocomplete)
> until they actually need to conform/subclass/extend.  Users won’t even need
> to learn about ‘hidden' until they are trying to extend a type which uses
> it (in a way which requires access to those internals), or they are writing
> their own framework.  It has a simple and consistent meaning based on
> Swift’s original file-based access, but allows power/flexibility (without
> too much bookkeeping/boilerplate) where needed.
>
> Thanks,
> Jon
>
>
> * One detail needed to make things useful for protocols, is that both
> hidden and non-hidden vars/methods on the conforming type should count
> towards conformance of hidden vars/methods on the protocol.  Basically,
> marking something as ‘hidden’ on a protocol means it isn’t seen by the
> caller (only conformers/extensions).  It makes sense to allow the conformer
> not to expose that either, unless desired.  It would technically work fine
> without this allowance, but it ‘feels right’ and people would ask for it
> quickly...
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170213/f1dabdba/attachment.html>


More information about the swift-evolution mailing list