[swift-evolution] [Pitch] Requiring proactive overrides for default protocol implementations.

Andrew Bennett cacoyi at gmail.com
Thu Apr 28 19:44:30 CDT 2016


Hey, what annotations would I have in this case:

Module 1:

Type AType { func foo() { ... } }

Module 2:

import Module1protocol A { func foo() {...default...} }extension AType: A {}



Also, for your *alternatives* section:

protocol A { func foo() {...default...} }Type AType: A {
    func A.foo() {...replacement...}
}


I actually prefer this alternative, I think it fixes many issues.


On Thu, Apr 28, 2016 at 12:47 PM, Erica Sadun via swift-evolution <
swift-evolution at swift.org> wrote:

>
> On Apr 27, 2016, at 6:03 PM, Douglas Gregor <dgregor at apple.com> wrote:
>
> 2) Is “override” only required when there is a default implementation of
> the protocol requirement, or is it required whenever you are implementing a
> protocol requirement?
>
>
> Override is only because it is overriding the default implementation of
> the protocol requirement. Without that default implementation there would
> be no override, it would simply be satisfying the requirement.
>
>
> For me, this doesn’t provide additional value of “required”: i.e., the
> value of having a keyword here is in telling me that I failed to implement
> a requirement when I’ve clearly said that I wanted to implement a
> requirement. Whether there was a default there or not isn’t really very
> interesting. Plus, a default could be added later to a requirement that I
> implement: that change has zero impact on how my code works (before or
> after), but now I’d be require to add an “override” keyword when I
> recompile.
>
> Contrast that with classes: if you recompile against a new version of a
> library and the compiler tells you that you need to add “override”, it’s
> serious because the semantics of your program will change if you’re now
> overriding something that you weren’t before.
>
>
> Consider these situations:
>
> * I use the word 'required' but I use a Double in the signature instead of
> a Float. Compiler detects. Instant alert on the mismatch.
> * I implement a required member but fail to use the word required.
> Compiler detects. Instant alert: this is a required member, did you intend
> to use this signature for that purpose?
> * I implement a required member. I then later provide a default. Compiler
> detects. "This version will be overridden by the default version the
> protocol and/or extension. Either remove this implementation or add the
> override keyword to prefer it to the default version."
> * I implement a default version and then later implement the required
> member. Compiler detects Same warning as above.
>
>
>
>
> * If the former, it might be the case that it’s too easy to forget to add
> the “override” keyword (because it’s needed for some implementations of
> protocol requirements but not others), which undercuts the value of having
> it.
>
>
> Forcing the override keyword makes it clear at the definition point that
> the story extends beyond the method or whatever to point to a default
> implementation that is being replaced. I *really* like having that
> reference in terms of both code construction (“I am doing this as a
> deliberate act”) with the compiler complaining otherwise, and in terms of
> code self documentation (“I know this was added deliberately, what default
> did it override?”)
>
>
> I see the former (“I am doing this as a deliberate act”)  as a very common
> complaint; the latter not nearly as much. What motivates that? And does it
> justify adding a *second* keyword to these declarations?
>
>
> I think I caught the gist in the situations above. If not, will respond
> further.
>
>
> I’d also like to bring up two related topics, although they probably
> should at some point move to their own thread if they have any legs:
>
>
> Related topic 1: How should a consumer handle a situation where two
> unrelated protocols both require the same member and offer different
> default implementations. Can they specify which implementation to accept or
> somehow run both?
>
> type B: A, C {
>     override required func foo() { A.foo(); C.foo() }
> }
>
>
> I think the right answer here is for the compiler to produce an ambiguity
> if you don’t implement the requirement yourself, and then solving your
> “related topic 2” lets you choose which implementation you want.
>
>
> How do you choose which one? What syntax? For example:
>
> required func foo = A.foo
>
> would be the simplest approach
>
>
> type B: A, C {
>   override required func foo() { A.foo(self)() }
> }
>
>
> +1
>
>
> Related topic 2: How can a consumer “inherit” the behavior of the default
> implementation (like calling super.foo() in classes) and then extend that
> behavior further. This is a bit similar to how the initialization chaining
> works. I’d like to be able to call A.foo() and then add custom follow-on
> behavior rather than entirely replacing the behavior.
>
> type B: A {
>     override required func foo() { A.foo(); … my custom behavior … }
> }
>
>
> Seems totally reasonable to me. One ugly syntax: A.foo(self)(), leveraging
> the currying of self?
>
>
> Ugly but it would pretty much do it for me. It offers an expressive way to
> say “Please execute the A.foo behavior using the self instance”. Does 3
> still support this?
>
>
> Probably not? I actually don’t know ;)
>
>
> I vaguely remember some stuff being changed. I'd normally try to test but
> I can't get a dev build to work in Xcode since the March 24 build. :(
>
> -- E
>
> _______________________________________________
> 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/20160429/8be10348/attachment.html>


More information about the swift-evolution mailing list