<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On 20 Sep 2016, at 18:43, Nevin Brackett-Rozinsky via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" class="">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 class=""><br class=""></div><div class="">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 class=""><br class=""></div><div class="">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 class=""><br class=""></div><div class="">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 class=""><br class=""></div><div class="">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 class=""></div><div class=""><br class=""></div><div class="">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 class=""><br class=""></div><div class="">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 class=""><br class=""></div><div class="">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 class=""><br class=""></div><div class="">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 class=""><br class=""></div><div class="">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 class=""><br class=""></div><div class="">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 class=""><br class=""></div><div class="">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 class=""><br class=""></div><div class="">Conforming types should not be afflicted with extraneous keywords: that would run contrary to the purpose of having protocols in the first place.<br class=""></div><div class=""><br class=""></div><div class="">Nevin</div><div class=""><br class=""></div></div><div class="gmail_extra"><br class=""><div class="gmail_quote">On Tue, Sep 20, 2016 at 11:16 AM, Xiaodi Wu via swift-evolution <span dir="ltr" class=""><<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>></span> wrote:<br class=""><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 class=""><div class="gmail_quote"><div dir="ltr" class="">On Tue, Sep 20, 2016 at 10:14 Vladimir.S via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a>> wrote:<br class=""></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br class="">
> extension P {<br class="">
> implement func foo() -> [String : String] { return [:] }<br class="">
> }<br class="">
<br class="">
Yes, it seems like we need `implement` (or `override` as another<br class="">
suggestion) in protocol extension also just for the same reasons - be clear<br class="">
about our intention regarding implementing the requirement, to show that<br class="">
this func *depends* on the previous definition of P protocol and to avoid<br class="">
possible mistakes related to protocol conformance.<br class="">
<br class="">
On 20.09.2016 17:38, Charles Srstka wrote:<br class="">
>> On Sep 20, 2016, at 8:17 AM, Vladimir.S via swift-evolution<br class="">
>> <<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a> <mailto:<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.<wbr class="">org</a>>> wrote:<br class="">
>><br class="">
>> On 20.09.2016 3:03, Xiaodi Wu via swift-evolution wrote:<br class="">
>>> I definitely think Vladimir's suggestion is a great starting point, IMO.<br class="">
>>><br class="">
>>> However, I think it could be improved in one key respect where previous<br class="">
>>> proposals using `override` are superior. Namely, the proposed `implement`<br class="">
>>> keyword adds no additional safety when a type implements a protocol<br class="">
>>> requirement that doesn't have a default implementation. This is because, if<br class="">
>><br class="">
>> Yes, *at the moment of writing* the type's code there could be no default<br class="">
>> implementation for protocol requirement. But, *at the moment of<br class="">
>> compilation* such default implementation could appear.<br class="">
>><br class="">
>> Let's discuss such scenario in case we'll take your suggestion:<br class="">
>><br class="">
>> You got SomeClass.swift file, 3rd party file you don't want to change or<br class="">
>> changes are not allowed. Content:<br class="">
>><br class="">
>> public protocol SomeProtocol {<br class="">
>> func foo()<br class="">
>> }<br class="">
>><br class="">
>> public class SomeClass : SomeProtocol {<br class="">
>> func foo() {...} // no default implementation *at the moment of writing*,<br class="">
>> no need in `overload`<br class="">
>> }<br class="">
>><br class="">
>> Now, you adds SomeClass.swift file to your project and in some *other*<br class="">
>> file you write:<br class="">
>><br class="">
>> extension SomeProtocol {<br class="">
>> func foo() {...}<br class="">
>> }<br class="">
>><br class="">
>> As you see, you don't control the SomeClass.swift but you suggest in this<br class="">
>> case SomeClass.foo() should be defined with `override`.<br class="">
>><br class="">
>> With 'implement' SomeClass.foo() will be marked initially and will save<br class="">
>> us if protocol's requirement PLUS default implementation changed.<br class="">
><br class="">
> Requiring the ‘implement’ keyword can help us even if no default<br class="">
> implementation is involved. Consider:<br class="">
><br class="">
> protocol P {<br class="">
> func foo() -> [String : Any]<br class="">
> }<br class="">
><br class="">
> struct S : P {<br class="">
> func foo() -> [String : String] { return [:] }<br class="">
> }<br class="">
><br class="">
> We will get an error here that S does not conform to P. However, this is<br class="">
> not the correct error, since S in fact *tries* to conform to P, but it has<br class="">
> a mistake in a method signature. This misleads us as to the true nature of<br class="">
> the problem, and if S has enough members in it that we fail to spot the<br class="">
> existing foo(), we might solve the problem by reimplementing foo(), and<br class="">
> leaving the original foo() as dangling dead code. Having an ‘implement’<br class="">
> keyword on the existing foo() function would change the compiler error to<br class="">
> let us know that we have an existing foo() that is incorrectly declared.<br class="">
><br class="">
> In addition, ‘implement’ can help us when the declaration in question *is*<br class="">
> the default implementation:<br class="">
><br class="">
> protocol P {<br class="">
> func foo() -> [String : Any]<br class="">
> }<br class="">
><br class="">
> extension P {<br class="">
> implement func foo() -> [String : String] { return [:] }<br class="">
> }<br class="">
><br class="">
> Here we will get an error with the proposed ‘implement’ keyword, because<br class="">
> foo() does not have a signature matching anything in the protocol, whereas<br class="">
> without ‘implement’ we would happily and silently generate a useless<br class="">
> dangling function that would never be used, and then pass the buck to the<br class="">
> concrete type that implements P:<br class="">
><br class="">
> protocol P {<br class="">
> func foo() -> [String : Any]<br class="">
> }<br class="">
><br class="">
> extension P {<br class="">
> func foo() -> [String : String] { return [:] } // The error is here:<br class="">
> }<br class="">
><br class="">
> struct S : P {} // But it gets reported here.<br class="">
><br class="">
> Charles<br class="">
><br class="">
______________________________<wbr class="">_________________<br class="">
swift-evolution mailing list<br class="">
<a href="mailto:swift-evolution@swift.org" target="_blank" class="">swift-evolution@swift.org</a><br class="">
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank" class="">https://lists.swift.org/<wbr class="">mailman/listinfo/swift-<wbr class="">evolution</a><br class="">
</blockquote></div>
</div></div><br class="">______________________________<wbr class="">_________________<br class="">
swift-evolution mailing list<br class="">
<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank" class="">https://lists.swift.org/<wbr class="">mailman/listinfo/swift-<wbr class="">evolution</a><br class="">
<br class=""></blockquote></div><br class=""></div>
_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></div></blockquote><br class=""></div><div><br class=""></div><div>I agree that a new keyword is unwanted. Conforming to protocols is quite a common thing, so you want it to be easy to remember.</div><div><br class=""></div><div>I think the best way is to prefix the member name with the protocol, e.g:</div><div><br class=""></div><div>protocol MyProto {</div><div> var aVariable : Int</div><div> func aFunction()</div><div>}</div><div>class MyClass : MyProto {</div><div> var MyProto.aVariable : Int</div><div> func MyProto.aFunction() { … }</div><div>}</div><div><br class=""></div><div>This is consistent with how we refer to other members of types (e.g. “extension MyClass.MyInternalClass”). It will be easy for autocompletion to provide good suggestions, too.</div><div>As I see it, the only problem is what if `MyClass` wants its own function called `aFunction()`? What if the same name satisfies 2 protocols, which do you write?</div><div><br class=""></div><div>The way to solve all of the problems in a consistent way is to make the function actually called “MyProto.aFunction”, and for it to be a separate function from plain “aFunction()” or from “SomeotherProto.aFunction”.</div><div><br class=""></div><div>I believe it is crucial to protocols that we can do this. Maybe I have some complex data structure and it has its own API, but I want people to be able to view it as a Collection. By conforming to Collection, I reserve lots of keywords and indexing operations which I now can’t use in my own API. Maybe I’m just providing Collection as a convenience to work with generic algorithms, but my own API has more efficient semantics for some operations. We’re relegated to using less-obvious and legible names in order to avoid conflicts.</div><div><br class=""></div><div>We have a way to work around this, which String uses - create a struct which references your object and calls internal methods such as “_collection_count” so you can have separate interfaces. This adds up to quite a lot of boilerplate and maintenance overhead.</div><div><br class=""></div><div>I don’t agree that Protocol conformances are kind-of incidental, as others here have written. This isn’t like Objective-C where anything that has the correctly-named methods conforms. Protocol conformances are completely explicit, and in fact we have empty protocols (“marker protocols”) for exactly that purpose. I think it is consistent that we make every member of a conformance specify which protocol it belongs to, and to have its name scoped to that protocol.</div><div><br class=""></div><div>Karl</div><br class=""><div class=""><br class=""></div><div class=""><div>CC-ing Dave A, to understand better if this fits with the vision of protocols</div></div><div class=""><br class=""></div></body></html>