[swift-evolution] Overriding protocol default implementation

Xiaodi Wu xiaodi.wu at gmail.com
Fri Feb 10 22:32:49 CST 2017


On Fri, Feb 10, 2017 at 9:54 PM, Rod Brown <rodney.brown6 at icloud.com> wrote:

>
>
> Sent from my iPhone
>
> On 11 Feb 2017, at 2:20 pm, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>
> On Fri, Feb 10, 2017 at 6:59 PM, Rod Brown <rodney.brown6 at icloud.com>
> wrote:
>
>> I don't believe these two worlds are in conflict at all.
>>
>> We currently have the default only state (without overrides), plus a
>> conflict. We would simply be adding "override" functionality in part to
>> clear the conflict.
>>
>> With POP the idea is that the protocol, in knowing about how it is
>> constituted, has a clear pattern for how it implements its behaviours.
>> Therefore you can leverage the protocol to bear the brunt of the work, just
>> as we do now.
>>
>> The additional tweak to the design of protocols is to allow a user to
>> define their own implementation where the default is not appropriate, or is
>> incomplete for the use case.
>>
>
> I think I've written a poor explanation of my point. In Swift, it is the
> library _author_, not the _user_, who gets the final say as to the upper
> limits on what users can do with the author's types, by using modifiers
> such as `final` and `open` (or the lack thereof). This has been the subject
> of vehement opposition but, nonetheless, it is a clear and opinionated
> decision on the part of the language. What you are critiquing as a bug is
> regarded as a feature. That is to say, it is a way for the author of a
> protocol extension method to deny to the user a customization point (in
> other words, to disallow the outright overriding of the "default" behavior).
>
>
>> This doesn't work against POP - it simply observes that implementations
>> at times may need to be customised to the use case, and allows that, as an
>> optional override.
>>
>
> Again, the status quo in Swift is that it is up to the protocol's author
> to determine which methods are overridable by the user and which are not.
> The idea is that protocol extension methods that are not protocol
> requirements are the intended way for disallowing such overriding.
>
> As to its practical use: this guarantees that if protocol `P` has a method
> `foo()`, it is possible to invoke `foo()` on an instance of existential
> type `P` knowing that you will invoke the intended method. A concrete type
> `T` that conforms to `P` may have its own `foo()` with totally different
> semantics. After all, if `foo()` is not a protocol requirement, then
> conforming types can have their own `foo()` do anything at all, with the
> collision in name being mere coincidence and no guarantee of similar
> semantics. And, with extensions, some third party can implement such a
> `foo()` on `T` that the library author has no way of reasoning about. By
> having a "shadowing" feature for `foo()`, I can know that no matter how
> anyone in the future extends type `T`, I will invoke the intended `foo()`
> with the right semantics on an instance of existential type `P`.
>
>
>> It's clear people are trying to do this already because they already have
>> overrides that are causing this conflict, and thus we are having the
>> discussion.
>>
>
> It sounds like what you are saying is that users of libraries are trying
> to "override" protocol extension methods that authors of libraries have
> designed not to be overridden. That this causes problems is, afaict, the
> intended consequence of this feature and not an overlooked bug. For maximum
> flexibility, however, Swift allows you to "shadow" the non-overridable
> method with an identically named method of your own design that can have
> different semantics.
>
>
> If the intent is to restrict users and to provide the power to the author
> of the protocol, it appears not just opinionated, but arrogant.
>
> As software developers, we need to work together to provide solutions to
> use cases. This includes not understanding what some use case may be. But
> instead, the consistent argument here has been that software should be as
> it is designed, to hell with the users of the frameworks who may have an
> unknown use case.
>
> This therefore has created the shadow problem, where people implementing a
> protocol end up colliding with the same name, and must make casts back.
>
> Why can't we make an adjustment and allow protocol implementers to define
> the cases where the protocol action is inappropriate.
>
> I believe this argument stems back to the closed-by-default argument on
> classes with "public" and shows a concerning trend in how Swift is being
> developed. We cannot look at Swift purely from the perspective of the
> Standard Library, or one framework, or one implementer. It is how we
> coordinate between framework authors that we end up creating a unified
> system.
>
> It should never be a feature to make users of frameworks fight with
> writers of frameworks. That's just absurd.
>

That's an unfair characterization. Certainly, `public` vs `open` was hotly
debated, but the Swift core team came down on one side of that debate after
weighing all the arguments. As you say, this functionality of protocol
extension members is of a kind to that decision, and in fact it pre-dates
that decision.

Let's be clear that it's not about making users of libraries "fight" with
authors of libraries. In a language where a user can retroactively extend a
type, these facilities can be critical for allowing library authors to
reason about their own code. These guarantees aren't only for the original
author, either. See the currently ongoing thread about introducing a
`closed` keyword and how knowledge about restrictions on how a class, enum,
struct, or protocol can be changed by another party can help any user
reason about their own code. As you can see above, I offered an example
where even an end user can rely on `P.foo()` to do the same intended thing
(where `P` is a protocol) no matter how anyone else extends a conforming
type `T`. This is not at all absurd but a practical boon.

Can it be inconvenient if you happen to be the user of a type `P` and want
a customization point where the author has not designed one? Sure. But no
more so than if you happen to be the user of a type `P` and want to access
a private member where the author has decided not to make it public. If we
deem this all absurd we'd not have access modifiers either, and we'd
abandon all the work on the roadmap about library resilience, which can
also constrain library authors to allow more freedom for library users.


> In this case, I don't see overriding the protocol "default" as working
>> against this world - I think it clarifies it.
>>
>> Rod
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170210/fc13e43e/attachment.html>


More information about the swift-evolution mailing list