<div dir="ltr">Thanks for the feedback David,<div><br></div><div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">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?</blockquote><div><br></div><div>In fact I *agree* with the lengthy points mentioned in the SE-0117 motivation section!</div><div><br></div><div>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.</div><div><br></div><div>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.”</div><div><br></div><div>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.</div><div><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">The reasons for the rarity above do not make much sense to me:<ul class="gmail-m_5452244504235950149MailOutline"><li><i>&quot;it must first of all be using classes rather than a protocol with conforming structs”: </i>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. </li></ul></blockquote><div>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.<br></div><div><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">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.</blockquote><br>That’s a bit harsh. For me, it has nothing to do with procrastination, but with being <b>safe-by-default</b>, which is an important Swift goal. You are arguing for <b>useful-by-default</b>, which is only a different priority.</blockquote><div><br></div><div>This is not an issue of safety. Classes are safe in Swift regardless of their visibility or finality.</div><div><br></div><div>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.</div><div><br></div><div>This model allows progressive disclosure:</div><div><ol><li>Classes are subclassable<br></li><li>‘final’ prevents subclassing<br></li><li>‘final(public)’ prevents external subclassing</li></ol></div><div><br></div><div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">I’m a proponent for going back to a file-based private but your solution has two big disadvantages for me:<ul class="gmail-m_5452244504235950149MailOutline"><li>it makes impossible to have a file-based scope in submodules</li></ul></blockquote><div>This is intentional. If you want certain files to share private details, then put them in the same submodule. Otherwise, don’t.</div><div><br></div><div>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.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><ul class="gmail-m_5452244504235950149MailOutline"><li><b>private</b> would have different semantics depending if its in a submodule or not.</li></ul></blockquote><div>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.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><ul><li>it would make copy-pasting/moving files from a submodule to a top-module potentially breaking:</li></ul></blockquote></div><div>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.</div><div><br></div><div><br></div><div> – Nevin</div></div></div>