[swift-evolution] [Pitch] consistent public access modifiers - protocols

Jordan Rose jordan_rose at apple.com
Wed Feb 15 20:23:25 CST 2017


> On Feb 10, 2017, at 12:23, Matthew Johnson <matthew at anandabits.com> wrote:
> 
> 
>> On Feb 10, 2017, at 12:52 PM, Jordan Rose <jordan_rose at apple.com <mailto:jordan_rose at apple.com>> wrote:
>> 
>> Hi, Matthew. Thank you for bringing up these issues. I'm going to break my feedback up into separate messages, because I think really the enum and protocol cases are unrelated. Open classes refer to classes that can be subclassed from clients of the current module, and similarly open protocols would be protocols that can be adopted from clients of the current module. Public-but-not-open classes cannot be subclassed from outside the current module, but they can still be subclassed within the module. By contrast, "open" enums can grow new cases in new versions of the library, but clients still can't add cases. (That's not a totally unreasonable feature to ever consider, but it's not the one we need now.)
> 
> Hi Jordan.  Thanks for replying to my post!
> 
> I understand the current behavior of `open` and how it would work for protocols.  I also understand the vocabulary that has been used in talking about “open” enums thus far.  What I am trying to point out is that there are inconsistencies in the vocabulary we’ve been using thus far.  
> 
> The ideas of “open” and “closed” both talk about who is able to add to the set of cases / subclasses / conforming types.  `public` (without annotation) also does this.  But we haven’t been using the terms consistently - we use a different meaning depending on which kind of entity we’re talking about.
> 
> For example, as you pointed out, `open` currently means both a module *and* its clients can add new subclasses.  It doesn’t seem right to use this same terminology to mean the module can add cases to an enum but clients *can’t* add new cases to the enum.  I understand that “open” enums in the sense of the current meaning of the `open` keyword are not a feature we need right away.  I noted that this is specifically not proposed in my pitch.  But if we ever *do* add this feature, `open enum` seems like the right way to spell it (probably just using the existing case syntax in an extension to add cases in the client).
> 
> It’s also worth pointing out that `public` currently has three distinct meanings:
> * `public` enums *cannot* have a new case added in a future version of the library is without a breaking change
> * `public` classes *can* have a new subclass added in a future version of the library without a breaking change, but clients cannot add subclasses
> * `public` protocols have the same semantics as `open` classes, allowing clients to add conforming types

* public structs *can* have new fields added
* public functions *can* add new parameters, as long as they have defaults, if you are careful about it
* public types *can* have new subtypes added
* public types *can* have new conformances added, although today that will break people and we need to do something about that (on another thread)

I think this is just a false equivalence. Adding cases to an enum within a module is fundamentally different from adding subclasses to a class outside the module. We should not be trying to jam enums into the same keyword that classes use just because I happened to use that term when writing the Library Evolution doc, even if it is a reasonable term for the thing.

(Matthew was very quick about replying to my first message and I was very slow with the second, and I think I already made this point better there. But for cross-referencing purposes it made sense to mention it here too.)


>> P.S. For classes, note that 'final' is essentially a performance optimization at this point. I'm not even sure we should bother displaying it in generated interfaces (although the compiler should still be able to take advantage of it in clients).
> 
> `final` can be pretty useful when reasoning about code.  It’s more than just a performance optimization.  It also represents a compiler proof about our code.

Ah, sorry, yes: 'final' is totally useful within a module to have the property enforced. It's just not super interesting outside the module. (It doesn't even mean there are no subclasses in all cases; features like KVO use a dynamic subclass in their implementation.)

Jordan
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170215/7fc6269b/attachment.html>


More information about the swift-evolution mailing list