Hi Vladmir! There is something very similar to this in C#. I like this but I'd like to enhance it a little bit. I don't think it's necessary to decorate protocol methods any further but some warnings by the compiler would be welcome, like when pushing a type to adopt a protocol through an extension when the type already implements a protocol method (we should need an annotation to tell the compiler we understand this). This would be my version of the proposal:
protocol IX { func somethingA() func somethingB() } class X { func somethingA() { ... } } @warn_implemented(IX.somethingA) // any better ideas? extension X : IX { func something() implements IX.somethingB { ... } } My issue here is: what if I need to adopt two protocols (from different vendors, I suppose) which require the same method and signature but for each interface you're expected to have a different outcome? I think better than just saying a method is an implementation required by a protocol is to say explicitly which protocol required that implementation. I'd also suggest a syntax for declaring a method that is not visible but through a cast to the protocol if that makes any sense to you. A method implementation can have a different name if you remember two different protocols could use the same name and signature; a new name would disambiguate them to us, the implements part would disambiguate for the compiler. What do you think? On 18 May 2016 at 04:28, Vladimir.S via swift-evolution <swift-evolution@swift.org> wrote: > I'd like to discuss declaration of protocol implementation in types. > > Ideas of this pitch is partially based on Erica Sadun's thread: > [Pitch] Requiring proactive overrides for default protocol implementations. > http://thread.gmane.org/gmane.comp.lang.swift.evolution/15496 > And on this draft of proposal: > https://gist.github.com/erica/fc66e6f6335750d737e5512797e8284a > > I had read "Winding down the Swift 3 release" message, but feel like this > proposal makes "improvements to the consistency and feel of the language" > and supports the "goal of making Swift 4 as source compatible with Swift 3 > as we can reasonably accomplish". Or this can be discussed as 'after Swift > 3.0' feature. > > > The main idea of my proposal > > Swift should help us to be explicit about what methods were defined in type > specifically to fulfill a protocol requirements. And so we will have more > understandable and self-documented code that is explicit regarding the fact > of protocol implementation(for reader of our code and for compiler). > > Additionally this can help to reduce potential > problems/error/misunderstanding in case some protocol requirement(method) > were *removed* - in this case (currently) our type will still have a method > as implementation but no such requirement in conformed protocol yet. > > > Details > > I propose to introduce *implement* keyword to 'mark' the methods(in type) > that were defined in order to conform to protocol. > Also, *reimplement* keyword is proposed to reflect the fact that method is > declared in *both* : in the type and in protocol extension (only in > extension, no definition of the method in protocol itself) > > > Rules > > * Each method in type defined to fulfill the protocol conformance should be > marked with `implement` keyword: > implement func protocolRequirement() {..} > > * Compiler produces *warning* if the same function is declared in type and > in protocol extension in case class conformed to that protocol. To 'fix' the > warning, `reimplement` should be used. > reimplement func f() {..} // we aware that the same method in protocol > extension > > * don't need to mark methods for type if conformance to protocol defined by > separate type extension > > * `reimplement` can be placed in defining type or as special declaration in > type extension anywhere in source code: > extension Type { > reimplement methodDeclaredInBothTypeAndInProtocolExtension(..); // no body > here. probably `;` is required - to be discussed > } > (I don't really like this requirement, but right now don't know if we can do > the same by using any other method ) > > > Current behavior of protocol extension > > When method is declared in protocol extension(*only. no in protocol itself*) > and in type that is conformed to the protocol, there is a possibility for > confusion about which method will be called. Example: > > protocol A { func a() } > extension A { func b() {print("Hello from b() in extension A")} } > > class B : A { > func a() {} > func b() {print("Hello from b() in B")} > } > > let instance1 = B() > instance1.b() // Hello from b() in B > > let instance2 : A = B() > instance2.b() // Hello from b() in extension A > > func f<T:A>(t: T) { t.b() } > f(instance1) // Hello from b() in extension A > > In this proposal I suggest compiler will generate a *warning* in this > case(not error). This warning can be fixed with `reimplement` keyword for > b() in class B. > > > `Override` keyword alternative > > I think that `override` keyword can not be used instead of new `implement`, > as the first clearly means now that method overrides one of the methods from > base class. Such method already has implementation in base class(in compare > with protocol requirement) and 'belongs' to `class` not to `protocol`. So, > in case of `override` keyword for protocol implementation we'll have > questions if super.method() should be called inside. > Also, usually declaration of `override` method is not required, in opposite > to implementation of protocol requirement. > > > Questions to discuss > > * Should `reimplement` be used only when exactly the same method > declared(arguments+return type the same) or even if just method name is the > same(in extension there is f(v: Float) in type f(v:Double)) ? I'd prefer the > second, but I don't feel this will be supported by community. > > > Code Examples: > > A) ------------------------------------------------ > > 1. We have some protocol: > > protocol A { > func a() > func b() > func c() > } > > 2. Then extension is defined for it: > > extension A { > implement func a() {} // Correct, `a` was declared in `A` > > //func b() {} > // Incorrect: `b` was declared in `A`, `implement` is required > // Compiler says: add `implement` keyword or remove implementation > > func d() {} // Correct, new method in extension > > //implement func e() {} > // Incorrect: `e` was not declared in `A`, `implement` should be removed > // Compiler says: remove `implement` keyword or remove implementation > } > > 3. *We* are writting the type S that conforms to A protocol: > > struct S: A { > implement func a() {} // Correct. We implemented A's requirement > > //func b() {} > // Incorrect: add `implement` keyword or rename the method > > implement func b() {} // Correct > implement func c() {} // Correct > > //implement func f() {} > // Incorrect: No `f` declaration in protocol. Compiler: rename method or > drop `implement` keyword > > //func d() {} > // Incorrect: Possible accidental name match. > // Compiler: rename method or add `reimplement` keyword > > reimplement func d() {} // Correct. We are explicit about the fact that > our type has the same function as in extension of conformed protocol > } > > > B) ------------------------------------------------ > > 1. Having declared protocol: > > protocol A { > func a() > func b() > func c() > } > > 2. Have defined extension > > extension A { > implement func a() {} // Correct, `a` was declared in `A` > > //func b() {} > // Incorrect: `b` was declared in `A`, `implement` is required > // Compiler says: add `implement` keyword or remove implementation > > func d() {} // Correct, new method in extension > > //implement func e() {} > // Incorrect: `e` was not declared in `A`, `implement` should be removed > // Compiler says: remove `implement` keyword or remove implementation > } > > 3. Have a type that we can't/don't want to change > > struct S { // at this moment S don't care about any protocol > func a() {} > func b() {} > func c() {} > func d() {} > } > > 4. *We* need (for some task) to conform the S type to protocol A in our own > code. So we do: > > extension S : A { > // no need of any special steps for a(), b(), c() > // as we just said "we sure S conforms to A" > > // but we need to care about special case - d() method, which is defined > in S type and in extension of A protocol > reimplement d(); // probably `;` is required here > } > > > C) ------------------------------------------------ > > 1. Have protocol > > protocol A { > func a() > func b() > func c() > } > > 2. Have a Type > > struct S { // at this moment S don't care about any protocol > func a() {} > func b() {} > func c() {} > func d() {} > } > > 3. Conforms to protocol > > extension S : A { > // no need of any special steps for a(), b(), c() > // as we just said "we sure S conforms to A" > // here(at the moment of *writing*) S don't know about any extension of > A > } > > 4. Now protocol extension is defined: > > extension A { > implement func a() {} // Correct, `a` was declared in `A` > > //func b() {} > // Incorrect: `b` was declared in `A`, `implement` is required > // Compiler says: add `implement` keyword or remove implementation > > func d() {} // Correct, new method in extension > } > > 5. But now we have a problem : same d() method in S and in A extension > Compiler will raise a warning : Possible accidental name match of d() in S, > also defined in extension of A. Change method name or add `reimplement` > keyword > > In case we can't or don't want to change the method name(in type or in > protocol) - the only solution is to say "it's OK" to the compiler anywhere > in our code: > > extension S { > reimplement d(); // notify the compiler that we are aware of the same > names > } > > Thank you for your opinions on this. > _______________________________________________ > 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