[swift-evolution] [Proposal] Sealed classes by default

Brent Royal-Gordon brent at architechies.com
Fri Jul 1 04:08:42 CDT 2016


> That starts to look an awful lot like a fifth access level just for classes (I know you're not proposing one, but it could start to look that way to a user).

You know, it *could* be.

Suppose that, in `internal` scope, you can do all of these things:

* Subclass a class.
* Add a case to an enum in an extension.[1]
* Add a stored property to a struct in an extension.
* Conform to a protocol (as opposed to just using and constraining with the existing conformances).
* Override an individual initializer, property, subscript, or method in an extension or subclass.[2]

But `public` does not permit them. You can *use* something that is public, but you can't extend it. `open`, on the other hand, *does* allow you to extend them. It means that outside code has (about) as much freedom to extend the `open` item as code inside your module does.

This approach would allow us to make the "sealing" very tight—if you changed a class from `public` to `open`, all of its `public` members would still be sealed—without actually making that a heavy burden on programmers who want things unsealed.

This also suggests that perhaps `final` is best thought of as foreclosing the things that `open` permits, either within a module or in future versions:

* A `final` class can never be subclassed.
* A `final` enum can never have cases added.
* A `final` struct can never have stored properties added.
* A `final` protocol...well, okay, that one's pretty useless. Maybe there just aren't `final` protocols.[3]
* A `final` property, subscript, or method can never be overridden.

A `final` thing would be fast both inside and outside the module, because it would have guarantees about its size/dynamic type/implementation; an `open` thing would be slow both inside and outside, because it would have no such guarantees; and a non-`final`, non-`open` thing would be slow externally but fast internally.



[1] There's another thread floating around where I've seen people suggest that enums could never be open because you couldn't unique integer raw values to each case. I think that's a rather narrow view of what an enum is for; many, perhaps most, enums don't need raw values, and even those that do could support string raw values with little danger.

[2] You can't currently override a member in an extension, but I think that would be essential for initializing extension stored properties and especially for adding cases to enums (you'd want to override members to handle your cases). 

[3] Or maybe a `final` protocol can't be conformed to directly, but only through a sub-protocol (which could only be defined within the module). That would allow arrangements like "Sequence is the parent protocol of both IteratorProtocol and Collection, but all Sequences must conform to one of those sub-protocols".

-- 
Brent Royal-Gordon
Architechies



More information about the swift-evolution mailing list