[swift-evolution] [Late Pitch] open/public protocols

Kevin Lundberg kevin at klundberg.com
Thu Aug 25 00:01:23 CDT 2016

On 8/22/2016 2:40 PM, Adrian Zubarev via swift-evolution wrote:
> Hello dear Swift community,
> I was updating some of my libraries where I noticed that the new
> |open| access modifier made the |public| modifier inconsistent in one way.
> Conformances to protocols is logically the same as inheritances on
> classes.
I don't understand why this is the case. From a practical perspective,
non-open classes by default were pushed in order to guard against the
fragile base class problem. Classes always carry implementations with
the methods you can override, while protocols don't (in the same way). A
"fragile base protocol extension implementation" problem can be avoided
today by designing your protocols properly. Not to mention that by
definition, protocols are designed to be conformed to by other types,
while not all classes are designed to be subclassed. What problem aside
from a perceived inconsistency would allowing for non-open protocols by
default solve?

>   * |Conformances == (abstract) inheritance|
> That said we should allow protocols to be |open/public| like we now
> allow this distinction for classes.
>   * |open protocol| from module A should mean that I’m allowed to
>     conform to it in module B
>   * |public protocol| will act as an interface in module B
> Not only sounds this behavior like ‘nice to have’, it’s inconsistency
> and it’s a ‘really need’ + a source breaking change in general.
> A common mistake in Swift 3.0 would be to hide protocol members behind
> |public| modifier for protocols that meant to be |open|. If a protocol
> member in an open class is disallowed to be overridden by the |public|
> modifier and this behavior is fixed, that will imply that you’ll have
> to open the member which you intended to be not overridable.
> |// Before: // In module A public protocol Proto { func doSomething() }
> open class Base : Proto { // Dissallow to override - this would be a
> common mistake public func doSomething() {} } // Used in module B - so
> it should be `open` after all class Test : Proto { func doSomething()
> {} } // After: // In module A open protocol Proto { func doSomething()
> } open class Base : Proto { // Whops we have to grant the ability to
> override this method now // I made a mistake designing my protocol in
> Swift 3.0 :/ open func doSomething() {} } // In module B class Test2 :
> Base { // Uuuuuuh I can do bad things with this now if the module A
> was not redesigned to fix this. :))) override func doSomething() {} } |
This example is a little confusing; do you mean that if protocols are
given the same open semantics as classes that there would be a
cross-module implementation problem? If so, isn't that an argument
against this?

I don't see a problem with just letting the class's open/public modifier
be the last word on any implemented public protocols. If a public
protocol is applied to an open class, then that protocol method should
be allowed to be declared as either open or public, which should be
enough to satisfy the protocol conformance from the protocol's perspective.
> Personally I don’t have any feeling of how huge the impact might be on
> Swift if this behavior will be fixed. I also cannot tell if it’s
> something for Swift 3.x or Swift 4.0.
> -- 
> Adrian Zubarev
> Sent with Airmail
> _______________________________________________
> 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/20160825/c62aa35e/attachment.html>

More information about the swift-evolution mailing list