[swift-evolution] [swift-evolution-announce] [Review #2] SE-0117: Default classes to be non-subclassable publicly

ilya ilya.nikokoshev at gmail.com
Wed Jul 20 18:52:52 CDT 2016


>  limiting “open” to public classes only lets you be sloppy inside your
own module.

I don't find that idea bad actually.

In the similar vein one can say "it's ok to be sloppy with local variable
names, it's not ok to be sloppy with instance variable names".

Again, tradeoffs. You can require that things are perfect, so that all
methods are thoughtfully annotated, and all variables have wonderful
self-descriptive names, but you'll get most bang for the buck by requiring
that for the interface (public classes / instance variables) rather than
for the implementation (non-public classes / local variables).




On Thu, Jul 21, 2016 at 12:26 AM, Karl via swift-evolution <
swift-evolution at swift.org> wrote:

>
> > On 20 Jul 2016, at 11:07, Brent Royal-Gordon <brent at architechies.com>
> wrote:
> >
> >> On Jul 19, 2016, at 6:14 PM, Karl <razielim at gmail.com> wrote:
> >>
> >> That is to say, we basically introduce “open" as an inverted “final”,
> and make all classes non-open by default. That is analogous to enabling
> whole-module-optimisation by default, in my opinion. The cost of an extra
> four-letter word isn’t that great, but the benefits to readability and
> reasonability all-around make it worthwhile.
> >
> > Okay, but this ignores an important difference between sealed and final.
> >
> > Sealed is *non-committal*. It makes no promises to wider scopes about
> whether there are other subclasses/overrides; it merely states that code
> outside the module may not subclass/override. `final`, on the other hand,
> is an *affirmative* statement: there are no subclasses/overrides and there
> never will be. Code outside the module is permitted to rely on that
> fact—for instance, it can generate static calls and conflate dynamic Self
> with static Self in conformances.
> >
> > But this distinction only really makes sense at the `public` boundary,
> because that's where the compiler—and even the developer—faces an
> impenetrable encapsulation barrier. If you want to require `open` even on
> non-public declarations, you thus need to choose one of these designs:
> >
> >       1. `final` is still available, but only on public APIs.
> >
> >       2. All non-public classes have to be explicitly declared either
> `open` or `final`.
> >
> >       3. Sealed has some sort of complex, scope-specific design (for
> instance, an `internal` class can be subclassed in `fileprivate` but not in
> `internal` scope).
> >
> > Of these three, I think that #2 is overly bureaucratic and #3 is overly
> complicated, so only #1 is a viable option. And then we're just choosing
> whether we have internal subclassing by default and an odd public-only
> `open` keyword, or no internal subclassing by default and an odd
> public-only `final` keyword. No viable option avoids some kind of asymmetry
> at the `public` boundary.
> >
> > Open-by-default with a `final` keyword is the traditional design. It is
> simpler for people learning to program and more familiar for people new to
> Swift. It is more convenient. And you just don't need the same rigorous,
> formal definition of semantics in internal scope, where you can alter a
> problematic invariant rather than having to live with it.
> >
> > All that said, there most likely *is* value in declaring, even
> internally, which classes are meant to be subclassed and which members are
> meant to be overridden. Perhaps what we ought to do is permit `open` even
> on non-public APIs, but not enforce it (or rather, leave enforcement to
> linters). That would allow people and teams to explicitly document internal
> overriding behavior if they want to, without burdening the teams that don't
> want to go to the effort.
> >
> > --
> > Brent Royal-Gordon
> > Architechies
> >
>
>
> This is exactly what I'm talking about - this is actually a very simple
> discussion. Throwing around words like “non-committal” and “affirmative”
> and speaking abstractly doesn’t disguise the brunt of what you’re saying:
> limiting “open” to public classes only lets you be sloppy inside your own
> module. That’s the only reason to make it like that. If I were describing
> the concept of “sloppiness” while trying my hardest not to use the word
> itself, I would probably say pretty much what you just wrote - wanting to
> remain non-committal, avoid definite, affirmative statements, etc.
>
> If we think it is important for people who write classes to locally reason
> about their code, it’s important full stop. The conflation between if it’s
> publicly accessible and whether or not is a staggeringly massive regression
> in read&reason-ability, no matter how matter how you want to phrase it.
> It’s a general problem which deserves a general solution - not some
> ‘non-committal’ proposal which can't even commit to the problem it is
> trying to help with.
>
> If you’ve ever had to deal with complex base classes, consisting of a
> mixture of internal (and possibly internally subclassed) members and public
> ones, you would know that annotating which members are to be used by what
> (and knowing that it’s enforced by the compiler) would be a massive
> improvement to our language syntax. Sometimes you didn’t write all the code
> you have to work with, so it’s handy to have code which annotates this
> stuff.
>
>
> Karl
>
>
>
> _______________________________________________
> 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/20160721/c02a8ca6/attachment.html>


More information about the swift-evolution mailing list