> On Apr 27, 2016, at 6:03 PM, Douglas Gregor <[email protected]> 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
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution