swift mixed implemention of protocol method and other method,this triggered the problem.<br><br>Compiler can&#39;t judge mis-spelled method. It think it&#39;s a new method.<br><br>Rust has no this problem:<br><br>Impl protocolName for className {<br>.....<br>}<br><br>linter can&#39;t check for mis-spelled methods, on the condition that there&#39;s no explicit override syntax in<br>Swift.<br><br><br><div class="gmail_quote"><div dir="ltr">Goffredo Marocchi via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt;于2016年9月20日 周二04:12写道:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="auto"><div><div style="direction:inherit">+1</div><br>Sent from my iPhone</div></div><div dir="auto"><div><br>On 19 Sep 2016, at 18:10, Vladimir.S via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt; wrote:<br><br></div><blockquote type="cite"><div><span>On 17.09.2016 6:32, Xiaodi Wu via swift-evolution wrote:</span><br><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>Let me give a concrete example of how retroactively modeling is used.</span><br></blockquote><span></span><br><span>Karl is suggesting interesting but complex and IMO too much code-breaking idea that I don&#39;t believe can be implemented at all in a reasonable amount of time to be a part of Swift as soon as possible, to address the discussed issue with protocols.</span><br><span></span><br><span>I wonder what objections could be made on the solution proposed below, which should solve a major(IMO) number of issues with protocol conformance and introduce only 1 keyword. Such solution will make Swift better as Protocol-Oriented language and later we can even improve it, but it can already solve a big number of issues:</span><br><span></span><br><span>1. As soon as possible we add &#39;implement&#39; keyword which is required to mark method/property that was defined in type or extension exactly to conform to some protocol.</span><br><span></span><br><span>2. The &#39;implement&#39; required only at a moment of &#39;direct&#39; conformance, i.e. when you declare methods/props of the type/extension that explicitly conformed to protocol.</span><br><span></span><br><span>3. Retrospective conformance will not require this keyword and will work for now just like it is working today.</span><br><span></span><br><span>4. Later, if this will be possible at all, we can extend this model to support separate implementation of protocols with same requirements in the same type, explicit protocol name in implemented methods/props and improvements for retrospective conformance. For example some variants for *future* improvements:</span><br><span></span><br><span>4.1 Different implementation for different protocols</span><br><span>class Foo : ProtocolA, ProtocolB {</span><br><span>  implement(ProtocolA) func foo() {...}</span><br><span>  implement(ProtocolB) func foo() {...}</span><br><span>}</span><br><span>class Foo : ProtocolA, ProtocolB {</span><br><span>  implement ProtocolA {</span><br><span>     func foo() {...}</span><br><span>  }</span><br><span>  implement ProtocolB {</span><br><span>     func foo() {...}</span><br><span>  }</span><br><span>}</span><br><span>etc</span><br><span></span><br><span>4.2 Retrospective conformance: What is the main problem with retrospective conformance? As I see it now(correct me, if I missing something), the problem arises in such situation:</span><br><span>* we *expect* that some method(s) in type will play the role of implementation of protocol&#39;s requirements, so we retrospectively conform that type to the protocol.</span><br><span>* but protocol has default implementation for its requirements</span><br><span>* and type&#39;s methods, that we *expect* to play roles for protocol implementation, has different parameters or slightly different method name at all.</span><br><span></span><br><span>I.e. when we have this set of code logic:</span><br><span></span><br><span>type T {</span><br><span>  func foo()</span><br><span>}</span><br><span></span><br><span>protocol P {</span><br><span>  func foo(x: Int)</span><br><span>}</span><br><span></span><br><span>extension P {</span><br><span>  func foo(x: Int) {...}</span><br><span>}</span><br><span></span><br><span>extension T : P { // expect foo in T will play role of P.foo</span><br><span>}</span><br><span></span><br><span>I support the opinion that it is not an option to require to explicitly list conformed methods/props in type extension for retrospective conformance.</span><br><span>But I do believe we need a way to *express our intention* regarding the retrospective conformance: do we expect that type already contains implementation for some protocol&#39;s requirements OR we are aware that protocol can have defaults for some methods and our type does not contains some implementations.</span><br><span></span><br><span>So, the solution here IMO is some syntax to express that intention. Right now I think that we can use current syntax &quot;extension T : P&quot; to keep it working as it now works: &quot;I&#39;m aware of all the names, defaults etc. Treat this as usually you did&quot;. But for example something like &quot;extension T: implement P {..}&quot; or &quot;extension T: P(implement *) {..}&quot; will say that we *expect* that all requirements of P protocol should be implemented inside T type. Or some syntax inside extension to specify the list of methods/props we expect to be implemented in T. Or &quot;extension T : P(implement foo, bar(x:y:)) {..}&quot;.. Should be discussed.</span><br><span></span><br><span>But again, IMO this could be discussed later, after we&#39;ll have &#39;implement&#39; for most important place - in type definition for method/prop that we created exactly for the conformed protocol.</span><br><span></span><br><span>Opinions?</span><br><span></span><br><blockquote type="cite"><span>Currently, there is a JIRA bug that Set does not conform to SetAlgebra. To</span><br></blockquote><blockquote type="cite"><span>fix this issue, someone simply needs to write `extension Set : SetAlgebra {</span><br></blockquote><blockquote type="cite"><span>}` and some tests. That&#39;s literally what the bug (filed by a core team</span><br></blockquote><blockquote type="cite"><span>member) tells you to do. It&#39;s a starter bug, and if someone hasn&#39;t taken it</span><br></blockquote><blockquote type="cite"><span>yet, you the reader could have a go at it. What&#39;s neat about Swift is that</span><br></blockquote><blockquote type="cite"><span>it&#39;s super easy to provide the same functionality in your own project</span><br></blockquote><blockquote type="cite"><span>without waiting on that bug to be fixed in Swift itself. You can simply</span><br></blockquote><blockquote type="cite"><span>write a single line of code. By contrast, if your proposal were to be</span><br></blockquote><blockquote type="cite"><span>implemented, this would become much more difficult.</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>This is actively used in Swift today. For example, in the Swift</span><br></blockquote><blockquote type="cite"><span>implementation of NSScanner, you&#39;ll find the following lines:</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>```</span><br></blockquote><blockquote type="cite"><span>internal protocol _BitShiftable {</span><br></blockquote><blockquote type="cite"><span>    static func &gt;&gt;(lhs: Self, rhs: Self) -&gt; Self</span><br></blockquote><blockquote type="cite"><span>    static func &lt;&lt;(lhs: Self, rhs: Self) -&gt; Self</span><br></blockquote><blockquote type="cite"><span>}</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>internal protocol _IntegerLike : Integer, _BitShiftable {</span><br></blockquote><blockquote type="cite"><span>    init(_ value: Int)</span><br></blockquote><blockquote type="cite"><span>    static var max: Self { get }</span><br></blockquote><blockquote type="cite"><span>    static var min: Self { get }</span><br></blockquote><blockquote type="cite"><span>}</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>extension Int : _IntegerLike { }</span><br></blockquote><blockquote type="cite"><span>extension Int32 : _IntegerLike { }</span><br></blockquote><blockquote type="cite"><span>extension Int64 : _IntegerLike { }</span><br></blockquote><blockquote type="cite"><span>extension UInt32 : _IntegerLike { }</span><br></blockquote><blockquote type="cite"><span>extension UInt64 : _IntegerLike { }</span><br></blockquote><blockquote type="cite"><span>```</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>If we adopted your proposed syntax below, it would take considerably more</span><br></blockquote><blockquote type="cite"><span>lines of boilerplate code to express the same thing. The burden increases</span><br></blockquote><blockquote type="cite"><span>significantly with the complexity of the retroactive modeling. For</span><br></blockquote><blockquote type="cite"><span>instance, if the retroactively modeled protocol had 20 requirements and you</span><br></blockquote><blockquote type="cite"><span>were retroactively conforming 20 types, that&#39;d be at least 400 lines of</span><br></blockquote><blockquote type="cite"><span>boilerplate.</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>    Basically, the way I see it, if my class MyClass implements MyProtocol,</span><br></blockquote><blockquote type="cite"><span>    providing someRequiredFunc(), there’s an “ownership” chain there</span><br></blockquote><blockquote type="cite"><span>    (reading it backwards).</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>    Now what happens if MyClass implements MyOtherProtocol, which also has</span><br></blockquote><blockquote type="cite"><span>    someRequiredFunc()? In that case, I want to MyClass as a</span><br></blockquote><blockquote type="cite"><span>    MyOtherProtocol and get another function pointer, which just happens to</span><br></blockquote><blockquote type="cite"><span>    have the same human-readable name as some other property. Just because</span><br></blockquote><blockquote type="cite"><span>    they have the same function signature, absolutely doesn’t mean they’re</span><br></blockquote><blockquote type="cite"><span>    the same thing.</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>    Now, if we strongly bind all protocol conformances to the protocol they</span><br></blockquote><blockquote type="cite"><span>    implement, what happens to instance methods? They don’t belong to any</span><br></blockquote><blockquote type="cite"><span>    protocol, their parent is the class itself. If you have an instance</span><br></blockquote><blockquote type="cite"><span>    method called someRequiredFunc(), and you later add a conformance to</span><br></blockquote><blockquote type="cite"><span>    MyProtocol, you would need to declare that it belongs to MyProtocol. If</span><br></blockquote><blockquote type="cite"><span>    you don’t want it to be an API-breaking change, you have to provide a</span><br></blockquote><blockquote type="cite"><span>    thunk (or we could provide a shorthand syntax which emits thunks for</span><br></blockquote><blockquote type="cite"><span>    you) to let us know that MyClass::someRequiredFunc() is the same thing</span><br></blockquote><blockquote type="cite"><span>    as MyClass::MyProtocol::someRequiredFunc().</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>Your argument is that two methods with the same name should not in any way</span><br></blockquote><blockquote type="cite"><span>conflict with each other. This is a fundamental change from the status quo.</span><br></blockquote><blockquote type="cite"><span>If we were to take your argument to its logical conclusion, any member A of</span><br></blockquote><blockquote type="cite"><span>a type T should be capable of being designated as the implementation of a</span><br></blockquote><blockquote type="cite"><span>requirement B of protocol P. In the most general case, two functions A and</span><br></blockquote><blockquote type="cite"><span>B shouldn&#39;t even need to take the same number of arguments, or arguments of</span><br></blockquote><blockquote type="cite"><span>the same type; you should be able to supply default arguments, or even</span><br></blockquote><blockquote type="cite"><span>write custom code that takes arguments for A and computes suitable</span><br></blockquote><blockquote type="cite"><span>arguments for B in order to forward A to B, and the language should allow</span><br></blockquote><blockquote type="cite"><span>you to designate A as an implementation of B. But that is simply not how</span><br></blockquote><blockquote type="cite"><span>Swift protocols are designed.</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>    Let’s take an example where retroactive modelling could go wrong.</span><br></blockquote><blockquote type="cite"><span>    You’ve got different teams working on different parts of an App, and</span><br></blockquote><blockquote type="cite"><span>    they’ve all got their own convention for “copy()”. Sometimes it’s a</span><br></blockquote><blockquote type="cite"><span>    deep-copy, sometimes a shallow-copy, sometimes it’s used in a fragile</span><br></blockquote><blockquote type="cite"><span>    way for a specific case, whatever. Now you want to go and clean that up</span><br></blockquote><blockquote type="cite"><span>    by creating a “Copyable” protocol with codified guarantees. Some</span><br></blockquote><blockquote type="cite"><span>    objects may already conform, others may need tweaks, and some may want</span><br></blockquote><blockquote type="cite"><span>    both behaviours simultaneously (preserving the old,</span><br></blockquote><blockquote type="cite"><span>    non-Copytable-compliant behaviour until the next API break), depending</span><br></blockquote><blockquote type="cite"><span>    on how you look at the object. A system like this allows all of those</span><br></blockquote><blockquote type="cite"><span>    different ways of looking at the object live together. You could have</span><br></blockquote><blockquote type="cite"><span>    the old, non-comforming API as an extension with a FIXME to delete it</span><br></blockquote><blockquote type="cite"><span>    for version 2.</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>Even if you design a protocol called Copyable, you still need to explicitly</span><br></blockquote><blockquote type="cite"><span>extend concrete types in order to conform to Copyable. Swift does not</span><br></blockquote><blockquote type="cite"><span>automagically make anything conform to your protocol. If you choose</span><br></blockquote><blockquote type="cite"><span>*explicitly* to conform different types that don&#39;t guarantee the same</span><br></blockquote><blockquote type="cite"><span>semantics, and then you erroneously assume that they all have the same</span><br></blockquote><blockquote type="cite"><span>semantics even though you *explicitly* chose types that don&#39;t have the same</span><br></blockquote><blockquote type="cite"><span>semantics, you&#39;re the one who shot yourself in the foot, so to speak. It&#39;s</span><br></blockquote><blockquote type="cite"><span>not the fault of Swift at all.</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>    I think it’s pretty arcane that members of a type are resolved only by</span><br></blockquote><blockquote type="cite"><span>    their names. If you want to provide types which allow flexible views of</span><br></blockquote><blockquote type="cite"><span>    data, each view of that data needs to be completely free in its</span><br></blockquote><blockquote type="cite"><span>    expressivity.</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>    I would actually like to see a syntax like:</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>    ```</span><br></blockquote><blockquote type="cite"><span>    let testObject = MyClass()</span><br></blockquote><blockquote type="cite"><span>    let testMyProto = testObject.MyProtocol // the protocol-witness table</span><br></blockquote><blockquote type="cite"><span>    for testObject as a MyProtocol.</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>    testObject.MyProtocol.someRequiredFunc() // that’s one function</span><br></blockquote><blockquote type="cite"><span>    testObject.someRequiredFunc() // is a different function. May happen to</span><br></blockquote><blockquote type="cite"><span>    have the same implementation as above if MyProtocol was retroactively</span><br></blockquote><blockquote type="cite"><span>    modelled.</span><br></blockquote><blockquote type="cite"><span>    ```</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>    I think it would fit well with the dispatch system for protocol</span><br></blockquote><blockquote type="cite"><span>    extensions, too. I sometimes have code like the following:</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>    ```</span><br></blockquote><blockquote type="cite"><span>    protocol Base {}</span><br></blockquote><blockquote type="cite"><span>    protocol Derived : Base {}</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>    extension Base {</span><br></blockquote><blockquote type="cite"><span>      func doSomething() { … }</span><br></blockquote><blockquote type="cite"><span>    }</span><br></blockquote><blockquote type="cite"><span>    extension Derived {</span><br></blockquote><blockquote type="cite"><span>      func doSomething() {</span><br></blockquote><blockquote type="cite"><span>       …</span><br></blockquote><blockquote type="cite"><span>       (self as Base).doSomething() // Would be better if we could say</span><br></blockquote><blockquote type="cite"><span>    “self.Base.doSomething()” to disambiguate instead of casting.</span><br></blockquote><blockquote type="cite"><span>      }</span><br></blockquote><blockquote type="cite"><span>    }</span><br></blockquote><blockquote type="cite"><span>    ```</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>This is a complete redesign of protocols in Swift. With the emphasis on</span><br></blockquote><blockquote type="cite"><span>minimizing source-breaking changes, I doubt such a change would be in scope</span><br></blockquote><blockquote type="cite"><span>for any phase of Swift unless you could show an overwhelming benefit.</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>    So yeah, a big +1 to marking protocol methods with their protocol</span><br></blockquote><blockquote type="cite"><span>    (whatever the syntax ends up looking like), and actually I’d take it</span><br></blockquote><blockquote type="cite"><span>    further and bake them in to the ABI. That also makes it relevant for</span><br></blockquote><blockquote type="cite"><span>    Swift 4 phase 1.</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>    Karl</span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><blockquote type="cite"><span>_______________________________________________</span><br></blockquote><blockquote type="cite"><span>swift-evolution mailing list</span><br></blockquote><blockquote type="cite"><span><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a></span><br></blockquote><blockquote type="cite"><span><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span><br></blockquote><blockquote type="cite"><span></span><br></blockquote><span>_______________________________________________</span><br><span>swift-evolution mailing list</span><br><span><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a></span><br><span><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span><br></div></blockquote></div>_______________________________________________<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/mailman/listinfo/swift-evolution</a><br>
</blockquote></div>