[swift-evolution] Simplifying Access Using 'Hidden'

Xiaodi Wu xiaodi.wu at gmail.com
Mon Feb 13 17:38:43 CST 2017


The beauty of Swift 2's access modifiers was that they were based around
files and modules, explicitly rejecting types and scopes as units for
determining visibility. It seems at base there's a group of people who
reject that decision altogether. Hence, new `private`, proposals around
`protected`, `friend`, `hidden`, `extensible`, etc.

The point of the other thread was that a sizable proportion of people are
finding the old system to be elegant and a suitable basis for future
enhancements such as submodules. Here, there's another proportion of people
who want to dismantle the old design completely. This was pitched already
during the Swift 3 evolution process, repeatedly.

At some point, we've got to stop relitigating this design. It's untenable
to have something as foundational as access control change with every
version of Swift.

My two cents are that supporting all the shades of private is completely a
non-goal. I've yet to be convinced that more access modifiers will improve
anyone's code sufficiently to justify any more turmoil in the language. The
Swift 2 way took a very pragmatic approach. When can I access this member?
If private: when I have the source code already open; if internal: when I
have the source code available to open; if public: whenever. It takes the
opinionated (but IMO correct) view that it's not particularly useful for
the compiler to hide something from you that you can plainly see and touch.


On Mon, Feb 13, 2017 at 5:04 PM, Joanna Carter via swift-evolution <
swift-evolution at swift.org> wrote:

> What still strikes me as odd is that we now seem to have a plethora of
> visibilities, some of which do not provide for a given context, some of
> which seem to be looking for a context to justify their existence.
>
> Whatever it is called, I find the idea of a file scope visibility somewhat
> bizarre and at odds with the principle of standard OO class encapsulation.
>
> The two main reasons I can see for the perceived need for fileprivate are :
>
> 1. being able to separate out "sections" of a class into various extensions
>
> 2. giving global junkies the ability to write all their code in one unit
>
> Surely, there are members of a type that the writer wants to remain
> private, even if an extension were declared in the same file. Fine, we have
> private for that and, even if the writer declares members to be
> fileprivate, there is no way that any extension declared outside of the
> file can see those members.
>
> Now, I have a problem with that. If I want to access non-public members
> when I extend a type, either I declare those extensions in the same unit
> and declare those members as fileprivate, or if I want to declare those
> extensions in another file, I have to move up to the next suitable scope,
> which is internal.
>
> But internal is too "open" because it allows, not only my chosen
> extensions to see those members but, also, any other code in the entire
> module.
>
> Having made use of the "friend" concept in C++, this "all or next to
> nothing" approach to visibility seems to leave me in much the same place as
> Objective-C, where I could only have private or public, unless I did some
> tricky stuff with class extensions, something which really didn't look that
> pretty.
>
> There are some parts of a type that I would want to remain really, really
> private to the type, not even visible to an extension.
>
> There are other parts of a type that I would want to be private to that
> type but also visible in, but only in, extensions explicitly written
> against that type.
>
> Which is why I am suggesting the "extensible" scope : private to the
> declaring type but also and only visible within any extension to that type.
>
> Here follows a highly contrived example :
>
> // Person.swift
> public struct Person
> {
>   public var name: String
>
>   public extensible(set) var dateOfBirth: Date
>
>   public var age: Int
>   {
>     // return calculated age as of today
>   }
>
>   init(name: String, dateOfBirth: Date)
>   {
>     self.name = name
>
>     self.dateOfBirth = dateOfBirth // accessible as if it were private
> }
>
> // Registrar.swift
> extension Person
> {
>   func correct(dateOfBirth: Date)
>   {
>     self.dateOfBirth = …
>   }
> }
>
> // Test.swift
> {
>   let person = Person()
>
>   person.dateOfBirth = … // compilation error, not visible
> }
>
> IMHO, this then removes one use case for fileprivate in that it allows
> privileged visibility to private members of a type in extensions, both in
> the same file and in any other file. But, it also ensures that not other
> code is allowed access, whether that be in non-extension code in the same
> file or other non-extension code anywhere else.
>
> As for case 2. for fileprivate, if a developer wants to put all sorts of
> globals and other code in one file, then I doubt if they are even going to
> bother to use fileprivate, especially when they get internal visibility
> with less typing ;)
>
> Now, if someone could help me prepare this as a proposal…
>
> --
> Joanna Carter
> Carter Consulting
>
> _______________________________________________
> 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/8108d361/attachment.html>


More information about the swift-evolution mailing list