[swift-evolution] A Comprehensive Rethink of Access Levels in Swift

Nevin Brackett-Rozinsky nevin.brackettrozinsky at gmail.com
Fri Feb 24 22:01:38 CST 2017


Thanks for the feedback David,

The whole design and motivation behind SE-0117 is that it is not rare to
> want classes to be freely subclass-able internally while being closed to
> subclassing externally. Do you have arguments to contradict the lengthy
> points mentioned in the SE-0117 motivation section?


In fact I *agree* with the lengthy points mentioned in the SE-0117
motivation section!

That document does an excellent job laying out why it is important for
Swift to support closed classes, and I am wholly on board with that
rationale. It is a major reason I dedicated so much space to explaining
that we *should* continue to support closed classes. However, SE-0117 makes
no attempt to dispute the fact that closed classes are rarely needed. After
all, one can often use structs or final classes instead.

Only at the very end of its motivation section does SE-0117 contain a few
brief lines about “excess annotations”, and it is there I take a different
view. Since closed classes are quite infrequent, it is acceptable to place
a short annotation on the declaration in order to specify, “Yes, this
really is supposed to be a closed class.”

The loss is small because it just means writing ‘final(public)’ on an
uncommon sort of declaration, and the win is large because it dramatically
simplifies our access control system.


The reasons for the rarity above do not make much sense to me:
>
>    - *"it must first of all be using classes rather than a protocol with
>    conforming structs”: *we are discussing the merits of the different
>    forms of subclassing prevention (public vs final), so I don’t see the
>    reason for mentioning structs.
>
> Any library which models its features using structs, does not need classes
at all, so it certainly does not need a closed class hierarchy. This is
part of the reason why closed classes are rare in Swift.


We should not make “soft defaults” that tend to negatively impact the
>> clients of a library for the dubious benefit of enabling its author to
>> procrastinate on a basic design decision. If someone truly wants to publish
>> a library with a closed class, then we should support that. But it should
>> be an intentional decision, not a default.
>
>
> That’s a bit harsh. For me, it has nothing to do with procrastination, but
> with being *safe-by-default*, which is an important Swift goal. You are
> arguing for *useful-by-default*, which is only a different priority.


This is not an issue of safety. Classes are safe in Swift regardless of
their visibility or finality.

I am putting forward the idea that Swift, being an opinionated language,
should take the stance, “Classes can be subclassed, unless they are
‘final’.” Then if a library author wants to restrict subclassing, they can
use ‘final’ or ‘final(public)’ to do so.

This model allows progressive disclosure:

   1. Classes are subclassable
   2. ‘final’ prevents subclassing
   3. ‘final(public)’ prevents external subclassing


I’m a proponent for going back to a file-based private but your solution
> has two big disadvantages for me:
>
>    - it makes impossible to have a file-based scope in submodules
>
> This is intentional. If you want certain files to share private details,
then put them in the same submodule. Otherwise, don’t.

The benefits are that it encourages people to keep submodules small and
focused, while supporting the pattern of building up types using
extensions, and without requiring lengthy files.


>    - *private* would have different semantics depending if its in a
>    submodule or not.
>
> I think my description may have been unclear. In my model there is only
one semantic meaning for ‘private’, and that is “visible in the submodule”.
Every file would naturally be its own submodule unless otherwise specified,
so the file-scope aspect is really just a consequence of having a submodule
with only one file in it.


>    - it would make copy-pasting/moving files from a submodule to a
>    top-module potentially breaking:
>
> Anytime code is moved out of a given visibility region, it will obviously
not be able to access things restricted to its previous location. This is
true of every access control system ever devised, and if I may be blunt it
is kind of the whole point.


 – Nevin
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170224/aba581a8/attachment.html>


More information about the swift-evolution mailing list