We've had this discussion on the list multiple times already. The gist of the difficulty here is that most proposals for a mandatory keyword don't permit retroactive modeling, so it's a no-go. On the other hand, the core team seems to take a dim view to optional syntax, since that's more in the ballpark of linters.
I really don't see anything new here that we haven't already discussed at length... On Fri, Sep 16, 2016 at 15:25 Adrian Zubarev via swift-evolution < swift-evolution@swift.org> wrote: > I don’t really like the idea of override(ProtocolName), but I’d support > the single override here. On value types it’s easier to recognize the > member of a protocol which had a default implementation. > > I don’t feel like adding override to all members that replaces some > default implementation will break anything. Furthermore, I’d love to see > the addition where we could call the default implementation. > > Here is some bikeshedding: > > protocol A {} > > extension A { > func foo() { .. } > } > > protocol B : A {} > > extension B { > // overriding default implementation from an other one!? > override func foo() { > // call default implementation of A > default.foo() > } > } > > struct C : A { > // overriding some default implementation > override func foo() { > // call default implementation > default.foo() > } > } > > struct D : B { > // overriding some default implementation > override func foo() { > // call default implementation B > // which will also call default implementation of A > default.foo() > } > } > > > > -- > Adrian Zubarev > Sent with Airmail > > Am 16. September 2016 um 20:45:05, Vladimir.S via swift-evolution ( > swift-evolution@swift.org) schrieb: > > David, thank you for a real-word example when such feature will be very > useful and can protect from hard-to-find bugs. IMO This shows that we > should find a solution for the problem as soon as possible. > > Such or similar question was discussed already in an number of threads, > for > example in "Requiring proactive overrides for default protocol > implementations." and in "Requiring special keyword to mark protocol > implementation methods", probably in other threads also. > > The first is that `override` is not used in structs, so IMO it will be > alien here. > Second, if protocol has no default implementation for the method- would > you > require the `override(Protocol)` also? > > Then, in case you will not require a keyword when no default > implementation > - you should think about retrospective adding of extension. > > I.e. imagine, you have a source file, let's call it SomeClass.swift which > you can't or don't want to change(this could be some complex source from > 3rd party, from github, or from other developer of your company). This > file > compiles without problems. It contains: > > public protocol Foo { func foo() } > public class Some: Foo { func foo() {...} } > > You added SomeClass.swift to your project and in your My.swift you added > default implementation for Foo protocol: > > extension Foo { func foo() {...} } > > So, now, when you compile your project, there is default implementation > for > foo() and class Some should contains `override(Foo)`, but you can't change > SomeClass.swift. > > > The only solution I see here, is if this `override(Foo)` will be optional, > and just express developer's intention, if he/she wants this. I.e. it is > not required, but if you specify it - compiler will check this intention. > But AFAIR unfortunately someone from core team mentioned that they don't > want such optional solution. > > And, at the end, I do think the real reason of your problem is not that > protocol method has default implementation, but that > `viewController(with:properties:)` definition in `FooController` does not > say for compiler(and compiler does not check this) that this method was > defined *exactly* to confirm to protocol. I.e. you can't clearly express > your intention regarding why this method is here. Check this example: > > Let's assume you defined protocol Foo in FooProto.swift file: > > public protocol Foo { func foo() } > > and have class `Some` conformed to Foo in SomeClass.swift: > > public class Some : Foo { func foo() {...} } > > it is clear *why* foo is here.. > > OK, now, let's assume you changed Foo protocol in the way, that > SomeClass.swift *still* compiles : > > public protocol Foo { func bar() } > extension Foo { > func bar() {...} > } > > Now, SomeClass.swift still compiles but it contains *wrong* intention that > foo() method is an implementation of protocol requirement. And this can > lead to bugs/unexpected behavior. > > > I think what we do need a way to clearly shows intention that we defined > some method *exactly* because the conformed protocol has it and to make > compiler check this. > > My favorite solution is 'implements' keyword inside class/struct to > highlight that I defined this method as implementation for the protocol > requirement. IMO solves a big percent of discussed issues with just one > added keyword, that also will help with understanding the code when you > read it. > > Other solution that was mentioned by (as I remember) member of core team > is > treat class extension with protocol conformance as such intention, i.e. > when you say > extension Some: Foo {..} > compiler will understand this as all methods inside such extension must > 'belongs' to the Foo protocol, i.e. if there is some method that does not > exist in Foo - it will raise an error. But in this case we need to require > that each protocol conformance will be declared as extension, not inline > in > class definition. Personally I don't believe in this solution. > > > On 16.09.2016 18:29, David Beck via swift-evolution wrote: > > With the transition from Swift 2 -> 3 IБ─≥ve started running into one > > particular issue VERY often (although itБ─≥s not necessarily specific to > the > > transition). If a protocol method is optional (either because it is an > > @objc optional or because it has a default implementation) there is a > risk > > that the conformer will have a misspelled or slightly incorrectly typed > > implementation of the method. For instance: > > > > protocolRouteDestinationViewController: class{ > > staticfuncviewController(with url: URL, properties: [String:String]) -> > > UIViewController? > > } > > > > extensionRouteDestinationViewControllerwhereSelf: UIViewController { > > staticfuncviewController(with url: URL, properties: [String:String]) -> > > UIViewController? { > > returnSelf.init() > > } > > } > > > > classFooController: UIViewController, RouteDestinationViewController{ > > staticfuncviewController(with url: URL, properties: [String:Any]) -> > > UIViewController? { > > returnFooController(properties: properties) > > } > > } > > > > Notice the issue there? Properties is supposed to be [String:String], but > > FooController uses [String:Any] (this is an exact issue I ran into after > a > > small refactor). When viewController(with:properties:) is called, it will > > use the default implementation instead of what the compiler sees as a > > completely different method. Over the betas the compiler has gotten > better > > warnings about this, but is still not 100%. > > > > Other cases of this issue are common with imported ObjC protocols that > have > > different naming in Swift. In some cases an @objc name must be applied to > > ensure it is declared in a way that the protocol can see it. > > > > We solve this problem with subclassing by requiring Б─°overrideБ─². If > the > > override keyword is present but the superclass doesnБ─≥t have a matching > > method, the compiler warns us about it. Similarly if the superclass > > implements the same method and the subclass doesnБ─≥t include override, > we > > get a warning so that it is clear that you are overriding behavior. > > > > For protocols, I donБ─≥t think a required keyword would be the best > approach. > > ItБ─≥s a completely valid case that a type could conform to a protocol > using > > existing methods, perhaps even from a different module. Further, a single > > method could satisfy multiple protocols, and be overriden from a > > superclass. What I would propose would be something like an optional > > override(<#protocol name#>). Something like the following: > > > > override(RouteDestinationViewController) staticfuncviewController(with > url: > > URL, properties: [String:Any]) -> UIViewController? { > > returnFooController(properties: properties) > > } > > > > A method should be able to include multiple overrides (including a bare > > override to indicate that it is overriding a class method). > > > > Thoughts? Are you seeing similar issues? > > > > *David Beck* > > http://davidbeck.co > > http://twitter.com/davbeck > > http://facebook.com/davbeck > > > > > > > > _______________________________________________ > > 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 > > _______________________________________________ > 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