[swift-evolution] [swift-evolution-announce] [Review] SE-0169: Improve Interaction Between private Declarations and Extensions
nevin.brackettrozinsky at gmail.com
Wed Apr 12 15:15:27 CDT 2017
In order to evaluate this proposal, I created a table of as many relevant
scenarios as I could think of, and listed how each of the proposed
solutions would work there. The four access level systems I compared are:
*No change:* The existing Swift 3 *status quo* with “fileprivate” and
*SE–0159:* Revert to the Swift 2 meaning of “private” (file visibility) and
eliminate scoped access altogether.
*SE–0169:* Expand “private” to include the current type and all its
extensions in the same file.
*Rename:* Change the spelling of “private” to “scoped”, and “fileprivate”
I ended up with a list of eight scenarios to evaluate. These are:
1. “Simple file”, a single type with no extensions.
2. “Extensions”, a single type and extensions thereof.
3. “Sharing”, multiple types that need privileged access to each other.
4. “Helper visible”, the interface of a helper (or nested) type for use
within the file.
5. “Helper hidden”, the details of a helper type that should not be visible
to other types.
6. “Invariants”, the details of a type that should only be touched by
7. “Multi-type”, multiple types that should not have privileged access to
8. “Multi-type + ext”, multiple types that should not have privileged
access to each other, and extensions thereof.
The entries in the table have seven possible values:
*private:* The “private” keyword works.
*fileprivate:* The “fileprivate” keyword works.
*scoped:* The “scoped” keyword works.
*private x2:* The “private” keyword works if the types are put into
*fileprivate x2:* The “fileprivate” keyword works if the types are put into
*helper type:* The goal can only be achieved by creating a helper type.
*no hiding:* The specified items cannot be hidden from the rest of the file.
Here is the completed and color-coded table (I hope it displays properly in
*Multi-type + ext*
Some people have said on-list that they view cross-type sharing as an
anti-pattern. If that is true, then we can simply ignore the “Sharing” row
because it would not be worth optimizing for. This hardly changes the table
though, as that row is identical to the “Helper visible” row below it.
Regarding the “Invariants” row, note that a helper type can be used for
this purpose under “No change” and “Rename” just as well as under
“SE–0169”. The difference is that SE-0169 provides no other way to hide
invariants from the rest of the type, whereas the other two have an access
level suited to the purpose. Similarly, the multi-type rows can be
satisfied by separate files regardless of which access system is in place.
If a person takes the view that things in the same file should naturally
have access to one another, then the bottom four rows of the table can be
ignored. Such a person might have the mantra, “Only put things together if
they belong together”, and they would ask, “What else is in the file that
you are trying to hide from?”
For someone whose primary use-case is to put one type in a file and build
it up through extensions, the “Extension” row is of greatest concern. To
them, any of SE–0159, SE–0169, or renaming would let them use “private”
instead of “fileprivate” everywhere.
As a final remark, each of the four options has one notable benefit and one
notable drawback, not all of which are apparent from the above table:
Benefit: No change to the language.
Drawback: Must use “fileprivate” to build up a type through extensions.
Benefit: Simplifies the access control model.
Drawback: Cannot protect invariants within a file.
Benefit: Cross-type sharing is clearly marked.
Drawback: Must use a helper type to protect invariants within a file.
Benefit: No change to semantics.
Drawback: Two separate keywords are changed.
• • •
And now, having said all that, I need to go take a nap!
Once everything has percolated, I’ll come back to write a review of the
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the swift-evolution