> 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

Reply via email to