Regards
(From mobile)

On Jul 1, 2016, at 6:43 PM, John McCall via swift-evolution 
<swift-evolution@swift.org> wrote:

>>> On Jul 1, 2016, at 2:08 AM, Brent Royal-Gordon <br...@architechies.com> 
>>> wrote:
>>> 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.
> 
> Yes, this is the way I've been thinking about it.
> 
>> 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.
> 
> This is an interesting thought.  Its application to 'struct', though, seems a 
> bit strange, since 'final' on classes doesn't remove the ability for the 
> module to change the stored properties (and clearly we wouldn't want it to do 
> so).
> 
>> [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.
> 
> If we know that an enum needs to be extensible, we can leave room in its 
> implementation for cases with arbitrary associated values.  This isn't a 
> problem.
> 
> Raw values are perhaps different.

This is a situation I often run into in jave where I would use an enum to 
create a finite set of constants to be passed (say action identifers). But then 
this makes it very difficult for external modules to extend the core set of 
actions locally. So i generally windup with an enum and an interface (the enum 
implements the interface).
Then local extensions are free to define their own local enums to cover only 
their local extensions to the original core set of actions. Then the public api 
definition constrains the action parameter to be enum&TheRequiredInterface. In 
the end this is a pattern I've come to like because tracing usage of the 
interface I can find all subsequent entensions to the core set of actions. Each 
subsequent set of extensions is just that: its own closed enum showing that 
they all form a coherent namespace for that extension (being a different enum 
than my original set, they do not prevent me extending the core set without 
risking name collisions with their extensions). The only cost is the heavier 
api declation site signature that is wearing the double enum & interface 
constraint.
The point is that you can extend enums without have to open them, and the 
resulting pattern may be even better than if you open the enum. The only 
hickup..... Swift does not let you express

protocol Command{}
func myCommand Handler<C: enum & Command>{}


>> [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).
> 
> Yes, I think allowing extensions to override members is an eventual goal.  It 
> needs runtime support, though, and some careful language design.
> 
>> [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".
> 
> It's okay for a modifier to not have meaning for absolutely everything. :)
> 
> John.
> _______________________________________________
> swift-evolution mailing list
> swift-evolution@swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to