On Apr 27, 2016, at 12:25 PM, Douglas Gregor <[email protected]> wrote:
> 
> On Apr 27, 2016, at 10:10 AM, Erica Sadun <[email protected] 
> <mailto:[email protected]>> wrote:
>> 
>> From the Swift Programming Language: Methods on a subclass that override the 
>> superclass’s implementation are marked with override—overriding a method by 
>> accident, without override, is detected by the compiler as an error. The 
>> compiler also detects methods with override that don’t actually override any 
>> method in the superclass.
>> 
>> I would like to extend this cautious approach to protocols, forcing the 
>> developer to deliberately override an implementation that’s inherited from a 
>> protocol extension. This would prevent accidental overrides and force the 
>> user to proactively choose to implement a version of a protocol member that 
>> already exists in the protocol extension.
>> 
>> I envision this as using the same `override` keyword that’s used in class 
>> based inheritance but extend it to protocol inheritance:
>> 
>> protocol A {
>>     func foo()
>> }
>> 
>> extension A {
>>     func foo() { .. default implementation … }
>> }
>> 
>> type B: A {
>> 
>>     override required func foo () { … overrides implementation … }
>> }
> 
> A couple questions about your pitch:
> 
> 1) What is “required” doing there? 

I threw it in not because I’m tied to it but because I wanted it to be part of 
the conversation.
This is a requirement from conforming to the protocol.

> 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.

>       * 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?”)

>       * If the latter, “override” is probably the wrong keyword because it’s 
> not overriding anything in the common case of implementing a non-defaulted 
> requirement.

It would be pointless if it’s just satisfying a requirement. That’s why  
introduced both keywords into the discussion. (And because I’m still being 
influenced by the “near miss” conversation.)

> 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

> 
>> 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?

> 
>> cc’ing in Jordan who suggested a new thread on this and Doug, who has 
>> already expressed some objections so I want him to  have the opportunity to 
>> bring that discussion here.
> 
> My objections are described here:
> 
>       http://thread.gmane.org/gmane.comp.lang.swift.devel/1799/focus=1831 
> <http://thread.gmane.org/gmane.comp.lang.swift.devel/1799/focus=1831>
> 
> Essentially, my argument is that the point of “override” (as pitched above) 
> is to declare the user’s intent to implement a requirement. I feel that the 
> explicit protocol conformance ("type B : A”) declares that intent, and that 
> various common conventions (e.g., one conformance per extension, where the 
> extension is primarily there to conform to the protocol) reinforce intent 
> well enough for the compiler to do a good job here. I’d prefer that over 
> another boilerplate-y keyword.
> 
>       - Doug
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to