<div dir="ltr">I have been following this discussion (as well as similar threads earlier this year) and listening to the ideas put forth by all sides.<div><br></div><div>It seems to me that the fundamental difference between classes and protocols is that classes inherit implementation whereas protocol conformance is a promise about interface.</div><div><br></div><div>When a class or struct or enum declares itself as conforming to a protocol, that means it has all the members specified in the protocol. The protocol conformance simply codifies a fact about the type itself: namely that all those members are present.</div><div><br></div><div>In this model, any keyword such as `implements` on each conforming member would introduce substantial boilerplate for negligible gain. The purpose of a protocol is to communicate that certain members are available, not to make declaring those members more onerous.</div><div><br></div><div>However, default implementations for protocols blur the line. Now there is actual implementation being inherited. A conforming type may choose to roll its own version of a method, or to utilize the default provided by the protocol. This is closer to the situation with subclassing.<br></div><div><br></div><div>Moreover, a protocol which conforms to another protocol may itself define (or redefine!) default implementations for members of that other protocol. This can create “inheritance chains” of protocol default implementations. I think there is value in being able to refer to (and call) the inherited default implementation through some sort of `super` functionality.</div><div><br></div><div>On the other hand, the existence of a default implementation in a protocol is in large part merely a convenience: a courtesy so that each conforming type need not rewrite the same boilerplate code.</div><div><br></div><div>A type which conforms to a protocol may accept the default or it may provide its own implementation, but it is not “overriding” anything. The default implementation was offered as a convenience, to be taken or left as needed. Thus I do not think any keyword (neither `override` nor `implements`) should be required in that case either.</div><div><br></div><div>The frequently-raised point regarding near-miss member names deserves some attention. Several people have expressed a desire for the compiler to assist them in determining whether a given member does or does not meet a protocol requirement. Specifically, when a type conforms to a protocol with a default implementation, and the type defines a member with a similar signature, it is not obvious at glance if that member matches the protocol.</div><div><br></div><div>I think this is a job for linters and IDEs. For example, syntax highlighting could distinguish members which satisfy a protocol requirement, thereby providing immediate visual confirmation of success.</div><div><br></div><div>Having followed the lengthy discussion and weighed the numerous ideas put forth, I come down firmly on the side of no keyword for protocol conformance.</div><div><br></div><div>A protocol describes an interface and provides a set of customization points. It may also, as a convenience, offer default implementations. The protocol simply describes the capabilities of its conforming types, and any default implementations are there to make things easier for them.</div><div><br></div><div>Conforming types should not be afflicted with extraneous keywords: that would run contrary to the purpose of having protocols in the first place.<br></div><div><br></div><div>Nevin</div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Sep 20, 2016 at 11:16 AM, Xiaodi Wu via swift-evolution <span dir="ltr">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">As I mentioned above, I agree that better diagnostics for near-misses are necessary, but they are possible without new syntax. There is no win in avoiding unintentional behavior because, without a default implementation, these issues are caught at compile time already.<div class="HOEnZb"><div class="h5"><br><div class="gmail_quote"><div dir="ltr">On Tue, Sep 20, 2016 at 10:14 Vladimir.S via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
 &gt; extension P {<br>
 &gt; implement func foo() -&gt; [String : String] { return [:] }<br>
 &gt; }<br>
<br>
Yes, it seems like we need `implement` (or `override` as another<br>
suggestion) in protocol extension also just for the same reasons - be clear<br>
about our intention regarding implementing the requirement, to show that<br>
this func *depends* on the previous definition of P protocol and to avoid<br>
possible mistakes related to protocol conformance.<br>
<br>
On 20.09.2016 17:38, Charles Srstka wrote:<br>
&gt;&gt; On Sep 20, 2016, at 8:17 AM, Vladimir.S via swift-evolution<br>
&gt;&gt; &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a> &lt;mailto:<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.<wbr>org</a>&gt;&gt; wrote:<br>
&gt;&gt;<br>
&gt;&gt; On 20.09.2016 3:03, Xiaodi Wu via swift-evolution wrote:<br>
&gt;&gt;&gt; I definitely think Vladimir&#39;s suggestion is a great starting point, IMO.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; However, I think it could be improved in one key respect where previous<br>
&gt;&gt;&gt; proposals using `override` are superior. Namely, the proposed `implement`<br>
&gt;&gt;&gt; keyword adds no additional safety when a type implements a protocol<br>
&gt;&gt;&gt; requirement that doesn&#39;t have a default implementation. This is because, if<br>
&gt;&gt;<br>
&gt;&gt; Yes, *at the moment of writing* the type&#39;s code there could be no default<br>
&gt;&gt; implementation for protocol requirement. But, *at the moment of<br>
&gt;&gt; compilation* such default implementation could appear.<br>
&gt;&gt;<br>
&gt;&gt; Let&#39;s discuss such scenario in case we&#39;ll take your suggestion:<br>
&gt;&gt;<br>
&gt;&gt; You got SomeClass.swift file, 3rd party file you don&#39;t want to change or<br>
&gt;&gt; changes are not allowed. Content:<br>
&gt;&gt;<br>
&gt;&gt; public protocol SomeProtocol {<br>
&gt;&gt; func foo()<br>
&gt;&gt; }<br>
&gt;&gt;<br>
&gt;&gt; public class SomeClass : SomeProtocol {<br>
&gt;&gt; func foo() {...} // no default implementation *at the moment of writing*,<br>
&gt;&gt; no need in `overload`<br>
&gt;&gt; }<br>
&gt;&gt;<br>
&gt;&gt; Now, you adds SomeClass.swift file to your project and in some *other*<br>
&gt;&gt; file you write:<br>
&gt;&gt;<br>
&gt;&gt; extension SomeProtocol {<br>
&gt;&gt; func foo() {...}<br>
&gt;&gt; }<br>
&gt;&gt;<br>
&gt;&gt; As you see, you don&#39;t control the SomeClass.swift but you suggest in this<br>
&gt;&gt; case SomeClass.foo() should be defined with `override`.<br>
&gt;&gt;<br>
&gt;&gt; With &#39;implement&#39; SomeClass.foo() will be marked initially and will save<br>
&gt;&gt; us if protocol&#39;s requirement PLUS default implementation changed.<br>
&gt;<br>
&gt; Requiring the ‘implement’ keyword can help us even if no default<br>
&gt; implementation is involved. Consider:<br>
&gt;<br>
&gt; protocol P {<br>
&gt; func foo() -&gt; [String : Any]<br>
&gt; }<br>
&gt;<br>
&gt; struct S : P {<br>
&gt; func foo() -&gt; [String : String] { return [:] }<br>
&gt; }<br>
&gt;<br>
&gt; We will get an error here that S does not conform to P. However, this is<br>
&gt; not the correct error, since S in fact *tries* to conform to P, but it has<br>
&gt; a mistake in a method signature. This misleads us as to the true nature of<br>
&gt; the problem, and if S has enough members in it that we fail to spot the<br>
&gt; existing foo(), we might solve the problem by reimplementing foo(), and<br>
&gt; leaving the original foo() as dangling dead code. Having an ‘implement’<br>
&gt; keyword on the existing foo() function would change the compiler error to<br>
&gt; let us know that we have an existing foo() that is incorrectly declared.<br>
&gt;<br>
&gt; In addition, ‘implement’ can help us when the declaration in question *is*<br>
&gt; the default implementation:<br>
&gt;<br>
&gt; protocol P {<br>
&gt; func foo() -&gt; [String : Any]<br>
&gt; }<br>
&gt;<br>
&gt; extension P {<br>
&gt; implement func foo() -&gt; [String : String] { return [:] }<br>
&gt; }<br>
&gt;<br>
&gt; Here we will get an error with the proposed ‘implement’ keyword, because<br>
&gt; foo() does not have a signature matching anything in the protocol, whereas<br>
&gt; without ‘implement’ we would happily and silently generate a useless<br>
&gt; dangling function that would never be used, and then pass the buck to the<br>
&gt; concrete type that implements P:<br>
&gt;<br>
&gt; protocol P {<br>
&gt; func foo() -&gt; [String : Any]<br>
&gt; }<br>
&gt;<br>
&gt; extension P {<br>
&gt; func foo() -&gt; [String : String] { return [:] } // The error is here:<br>
&gt; }<br>
&gt;<br>
&gt; struct S : P {} // But it gets reported here.<br>
&gt;<br>
&gt; Charles<br>
&gt;<br>
______________________________<wbr>_________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-<wbr>evolution</a><br>
</blockquote></div>
</div></div><br>______________________________<wbr>_________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-<wbr>evolution</a><br>
<br></blockquote></div><br></div>