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

Brent Royal-Gordon brent at architechies.com
Wed Jul 20 20:41:44 CDT 2016

> On Jul 20, 2016, at 3:26 PM, Karl <razielim at gmail.com> wrote:
>> 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.
> 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.

No, that is *not* the only reason. The other reason is library evolution.

A class that is closed in 1.0 can be opened in 1.1; a class that is `final` in 1.0 *cannot* be opened in 1.1 (or at least it's a breaking change if it is). This is a really important distinction for binary compatibility—but binary compatibility only matters at the public boundary. An `internal`-or-less class does not have to worry about maintaining a compatible binary interface between different versions, but a `public` class does.

When I say it's "non-commital", that's what I mean: It does not commit future versions of the module to either permit or forbid subclasses. A future version can either make it `open` or `final` as the module's evolving design demands. A `final` class must remain `final` forever. It's the difference between a door that's locked and a door that's bricked up.

Yes, it is *also* true that sealed-by-default permits sloppiness as long as it's contained to internal scope. But that's quite typical of Swift. It's why the default access control is `internal`, not `private` (the minimally-sloppy solution) or `public` (the minimally-bureaucratic solution). But these are two independent arguments for sealed. Railing against internal sloppiness doesn't change the library evolution argument.

Brent Royal-Gordon

More information about the swift-evolution mailing list