On 20.09.2016 19:43, Nevin Brackett-Rozinsky via swift-evolution wrote:
I have been following this discussion (as well as similar threads earlier
this year) and listening to the ideas put forth by all sides.


Yes, to do nothing and to have fragile protocol oriented programming is an another alternative. I can understand your opinion but can't agree.

About IDEs - I believe you know what I want to say ;-) In short - we are discussing Swift *language* and there is not only one IDE in this word and even with it nobody knows how long you will wait for such feature and *if* it will be implemented. So, IMO not an option.

About linters. Imagine you added complex 3rd party source code to your project. You use your own linter with your own rules. You see a number of warnings from your linter in that 3rd party code. Of course, the developer of that code was not using your linter with your settings, so there are a lot of warning. You see some warning regarding "near-miss" methods/properties in different places of that code. So, what next?

How linter will protect your project in this case from the discussed problem? In case developer of that 3rd party sources will have to express intentions - your project will be in safe, or theirs sources will not compile at all.


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.

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.

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.

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.

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.

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.

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.

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.

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.

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.

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.

Conforming types should not be afflicted with extraneous keywords: that
would run contrary to the purpose of having protocols in the first place.

Nevin


On Tue, Sep 20, 2016 at 11:16 AM, Xiaodi Wu via swift-evolution
<swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:

    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.

    On Tue, Sep 20, 2016 at 10:14 Vladimir.S via swift-evolution
    <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:


         > extension P {
         > implement func foo() -> [String : String] { return [:] }
         > }

        Yes, it seems like we need `implement` (or `override` as another
        suggestion) in protocol extension also just for the same reasons -
        be clear
        about our intention regarding implementing the requirement, to show
        that
        this func *depends* on the previous definition of P protocol and to
        avoid
        possible mistakes related to protocol conformance.

        On 20.09.2016 17:38, Charles Srstka wrote:
        >> On Sep 20, 2016, at 8:17 AM, Vladimir.S via swift-evolution
        >> <swift-evolution@swift.org <mailto:swift-evolution@swift.org>
        <mailto:swift-evolution@swift.org
        <mailto:swift-evolution@swift.org>>> wrote:
        >>
        >> On 20.09.2016 3:03, Xiaodi Wu via swift-evolution wrote:
        >>> I definitely think Vladimir's suggestion is a great starting
        point, IMO.
        >>>
        >>> However, I think it could be improved in one key respect where
        previous
        >>> proposals using `override` are superior. Namely, the proposed
        `implement`
        >>> keyword adds no additional safety when a type implements a protocol
        >>> requirement that doesn't have a default implementation. This is
        because, if
        >>
        >> Yes, *at the moment of writing* the type's code there could be
        no default
        >> implementation for protocol requirement. But, *at the moment of
        >> compilation* such default implementation could appear.
        >>
        >> Let's discuss such scenario in case we'll take your suggestion:
        >>
        >> You got SomeClass.swift file, 3rd party file you don't want to
        change or
        >> changes are not allowed. Content:
        >>
        >> public protocol SomeProtocol {
        >> func foo()
        >> }
        >>
        >> public class SomeClass : SomeProtocol {
        >> func foo() {...} // no default implementation *at the moment of
        writing*,
        >> no need in `overload`
        >> }
        >>
        >> Now, you adds SomeClass.swift file to your project and in some
        *other*
        >> file you write:
        >>
        >> extension SomeProtocol {
        >> func foo() {...}
        >> }
        >>
        >> As you see, you don't control the SomeClass.swift but you
        suggest in this
        >> case SomeClass.foo() should be defined with `override`.
        >>
        >> With 'implement' SomeClass.foo() will be marked initially and
        will save
        >> us if protocol's requirement PLUS default implementation changed.
        >
        > Requiring the ‘implement’ keyword can help us even if no default
        > implementation is involved. Consider:
        >
        > protocol P {
        > func foo() -> [String : Any]
        > }
        >
        > struct S : P {
        > func foo() -> [String : String] { return [:] }
        > }
        >
        > We will get an error here that S does not conform to P. However,
        this is
        > not the correct error, since S in fact *tries* to conform to P,
        but it has
        > a mistake in a method signature. This misleads us as to the true
        nature of
        > the problem, and if S has enough members in it that we fail to
        spot the
        > existing foo(), we might solve the problem by reimplementing
        foo(), and
        > leaving the original foo() as dangling dead code. Having an
        ‘implement’
        > keyword on the existing foo() function would change the compiler
        error to
        > let us know that we have an existing foo() that is incorrectly
        declared.
        >
        > In addition, ‘implement’ can help us when the declaration in
        question *is*
        > the default implementation:
        >
        > protocol P {
        > func foo() -> [String : Any]
        > }
        >
        > extension P {
        > implement func foo() -> [String : String] { return [:] }
        > }
        >
        > Here we will get an error with the proposed ‘implement’ keyword,
        because
        > foo() does not have a signature matching anything in the
        protocol, whereas
        > without ‘implement’ we would happily and silently generate a useless
        > dangling function that would never be used, and then pass the
        buck to the
        > concrete type that implements P:
        >
        > protocol P {
        > func foo() -> [String : Any]
        > }
        >
        > extension P {
        > func foo() -> [String : String] { return [:] } // The error is here:
        > }
        >
        > struct S : P {} // But it gets reported here.
        >
        > Charles
        >
        _______________________________________________
        swift-evolution mailing list
        swift-evolution@swift.org <mailto:swift-evolution@swift.org>
        https://lists.swift.org/mailman/listinfo/swift-evolution
        <https://lists.swift.org/mailman/listinfo/swift-evolution>


    _______________________________________________
    swift-evolution mailing list
    swift-evolution@swift.org <mailto:swift-evolution@swift.org>
    https://lists.swift.org/mailman/listinfo/swift-evolution
    <https://lists.swift.org/mailman/listinfo/swift-evolution>




_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to