<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div><div style="direction: inherit;"><br></div>Sent from my iPhone</div><div><br>On 21 Sep 2016, at 01:41, Zhao Xin <<a href="mailto:owenzx@gmail.com">owenzx@gmail.com</a>> wrote:<br><br></div><blockquote type="cite"><div><div dir="ltr"><div class="gmail_default" style="font-family:georgia,serif">> <span style="font-size:12.800000190734863px;font-family:arial,sans-serif">I am not sure why protocol extension need to differ so much and present dispatch rules that are potentially very confusing. </span></div><div class="gmail_default" style="font-family:georgia,serif"><span style="font-size:12.800000190734863px;font-family:arial,sans-serif"><br></span></div><div class="gmail_default"><span style="font-size:12.800000190734863px">I think that both the Java and Swift designers want to get the benefits of multiple inherences, in the meaning time, they don't want to support multiple objects inherence. </span></div><div class="gmail_default"><span style="font-size:12.800000190734863px"><br></span></div><div class="gmail_default">For Java only, as Java allows implicit override, the `@override` is optional. Related bugs are hard to find if you don't use `@override`.</div><div class="gmail_default"><br></div><div class="gmail_default">For me, the current rule is simple. </div><div class="gmail_default">1. If there is a `override`, it is "class dynamic binding". If there is no `override`, it is not. The dynamic type of `self` is irrelevant.</div><div class="gmail_default">2. The method in 'protocol extension` is default, which means fail safe. It is not a method of a class until the class implements it.</div><div class="gmail_default" style="direction: inherit;"><br></div></div></div></blockquote><div style="direction: inherit;"><br></div><div style="direction: inherit;">Classic dynamic binding has its charms yes ;).</div><div style="direction: inherit;"><br></div><div style="direction: inherit;">To be on point, once you adopt the protocol, and thus the extensions that may also have been declared and the default methods, and you decide to override or happen to override the default implementation it is still not enough to make sure you will call your implementation in your own code. If the reference to the instance of the class is cast to the protocol type, I want other object to be aware of my API contract not the specific class instance, then the protocol default method gets called and that is several shades of not appropriate for me.</div><div style="direction: inherit;"><br></div><div style="direction: inherit;"><a href="https://nomothetis.svbtle.com/the-ghost-of-swift-bugs-future">https://nomothetis.svbtle.com/the-ghost-of-swift-bugs-future</a> (with subclassing this can get more complicated)</div><div style="direction: inherit;"><br></div><div style="direction: inherit;">Reasoning:</div><div style="direction: inherit;"><a href="https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151207/001922.html">https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151207/001922.html</a></div><div style="direction: inherit;"><br></div><div style="direction: inherit;">... hence why turning protocol dispatching into dynamic dispatching, unless the user says otherwise (@Kevin: sometimes it makes the language easier to use without sacrificing speed if we renounce a tad of purity and accept a dedicated keyword as compiler hint... a simple @static or something would suffice).</div><div style="direction: inherit;">Updating a version of a binary framework could be covered in extra perils you do not need.</div><div style="direction: inherit;"><br></div><blockquote type="cite"><div><div dir="ltr"><div class="gmail_default">Zhaoxin</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Sep 21, 2016 at 4:10 AM, Goffredo Marocchi <span dir="ltr"><<a href="mailto:panajev@gmail.com" target="_blank">panajev@gmail.com</a>></span> wrote:<br><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">This would make for hilarious debugging session if you have the misfortune of using a third party binary framework that gets updated and provide default implementations for some methods in the protocol extensions.</div><div style="direction:inherit"><br></div><div style="direction:inherit">When Java 8 also decided to blur the lines between classes (implementations) and interfaces (equivalent of protocols on this side of the fence more or less... anyways they represent behaviours/API contracts), they also provided a very simple rule to determine on the code would behave at runtime.</div><div style="direction:inherit"><h2></h2><blockquote type="cite"><h2><a name="m_-7356412064479119979_extending" style="background-color:rgba(255,255,255,0)"><font color="#000000" size="3">Extending Interfaces That Contain Default Methods</font></a></h2><p><span style="background-color:rgba(255,255,255,0)">When you extend an interface that contains a default method, you can do the following:</span></p><ul><li><span style="background-color:rgba(255,255,255,0)">Not mention the default method at all, which lets your extended interface inherit the default method.</span></li><li><span style="background-color:rgba(255,255,255,0)">Redeclare the default method, which makes it <code>abstract</code>.</span></li><li><span style="background-color:rgba(255,255,255,0)">Redefine the default method, which overrides it.</span></li></ul></blockquote></div><div style="direction:inherit"><a href="https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html" target="_blank">https://docs.oracle.com/<wbr>javase/tutorial/java/IandI/<wbr>defaultmethods.html</a></div><div style="direction:inherit"><br></div><div style="direction:inherit">I am not sure why protocol extension need to differ so much and present dispatch rules that are potentially very confusing. </div><div style="direction:inherit"><br></div><div style="direction:inherit">Casting at runtime should *never* change what implementation of a method gets called. </div><div style="direction:inherit">For a safe by default language the fact that this can occur is quite puzzling and worrying. I am not sure the cost of implementing the current static/dynamic dispatch rules for default methods in protocol extensions is worth it to say it bluntly, but please enlighten me if I am missing an obvious huge pink elephant in the room here.</div><div style="direction:inherit"><br></div>Sent from my iPhone</div><div><div class="h5"><div><br>On 20 Sep 2016, at 16:18, Nevin Brackett-Rozinsky via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>> wrote:<br><br></div><blockquote type="cite"><div><div dir="ltr">I think there is a deeper issue that may be worth exploring here.<div><br></div><div>Notably, when one class presents a member function, its subclasses ought to use “override” when they reimplement that method themselves, regardless of where the superclass’s version comes from.</div><div><div><br></div><div>In the original post, the class “A” expresses (by conforming to protocol “Foo”) that it has a member function “bar()”, and “B” is a subclass of “A” which wants its own definition of “bar()”.</div><div><br></div><div>It seems to me that “B” should not care whether “A” rolled its own implementation of “bar()” or used the default implementation provided by “Foo”.</div><div><br></div><div>From the perspective of “B”, its superclass “A” promises to have a member function “bar()”, so “B” should need to use the `override` keyword just like it would when overriding any other method.</div><div><br></div><div>To illustrate this more clearly, suppose that “Foo” and “A: Foo” are defined in a 3rd-party library, while “B: A” is written in a client module.</div><div><br></div><div>If the library changes to give “A” its own custom implementation of “bar()”, that *should not* affect client code—because the class “A” still conforms to “Foo” so it still is known to have a “bar()” method—but right now it *does*:</div><div><br></div><div>With the status quo, the simple change of moving a function between a protocol extension and a conforming class currently requires downstream source-code modifications in clients (in this case, adding `override` to “B.bar()”).</div><div><br></div><div>I propose that `override` should be required in subclasses on any method which the superclass proffers as a customization point, no matter the provenance of that claim.</div><div><br></div><div>Nevin</div><div><br></div><div><br></div></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Sep 20, 2016 at 8:01 AM, Zhao Xin via swift-evolution <span dir="ltr"><<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div class="gmail_default"><font face="georgia, serif">Thank you to Игорь Никитин and Adrian Zubarev. Now I can convince myself for this behavior.</font></div><div class="gmail_default"><font face="georgia, serif"><br></font></div><div class="gmail_default"><span style="font-family:georgia,serif">As Adrian's example shows, there is no `</span><font face="georgia, serif">bar()` implemented in `class A`, so there is no `override func bar()</font><span style="font-family:georgia,serif">` in class B`. My thought that </span><span style="color:rgb(0,0,0);font-family:georgia,serif;font-size:13px"> </span><span style="color:rgb(0,0,0);font-family:georgia,serif;font-size:13px">`self.bar()` would do the same as `(self as! B).bar()`, is called "dynamic binding", which is basing on the `override`. Since there is no `override`, there is no "dynamic binding". I thought "dynamic binding" was basing on dynamic type of `self`. It was not. I was wrong.</span></div><div class="gmail_default"><span style="color:rgb(0,0,0);font-family:georgia,serif;font-size:13px"><br></span></div><div class="gmail_default"><span style="color:rgb(0,0,0);font-family:georgia,serif;font-size:13px">The behavior is clear now. In class A's `</span><font color="#000000" face="georgia, serif">self.bar()`, the runtime finds that there is no implementation of `bar()` in `class A`, so it calls the `bar` in protocol extension. In class A's `(self as! B).bar()`, as `class B` contains the implementation of `bar()`, the runtime calls it.</font></div><div class="gmail_default"><span style="color:rgb(0,0,0);font-family:georgia,serif;font-size:13px"><br></span></div><div class="gmail_default"><span style="color:rgb(0,0,0);font-family:georgia,serif;font-size:13px">Zhaoxin</span></div></div><div class="gmail_extra"><br><div class="gmail_quote"><div><div>On Tue, Sep 20, 2016 at 4:21 PM, Adrian Zubarev via swift-evolution <span dir="ltr"><<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>></span> wrote:<br></div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div><div style="word-wrap:break-word"><div><p>I can’t tell you the reason, but to me it feels like it’s doing the following thing:</p>
<pre><code>+ - - (Type: B) - - +
| |
| func bar() + - + (Type: A) - - + < - - - - - - - - - - - - - - - - - - - - +
| | | |
+ - - - - - - - + func output() + - + (Protocol: Foo) - - + — - self.bar() - + - (self as! B).bar() - +
| | | |
+ - - - - - - - + (default) func bar() | <- - - - - - - - +
| |
+ - - - - - - - - - - - - +
</code></pre>
<pre><code>class A:Foo {
func bar() {}
func output() {
print(type(of:self))
self.bar()
(self as! B).bar()
}
}
class B:A {
override func bar() {
print("I am B.")
}
}
</code></pre>
<p>Would solve this temporarily.</p>
<p>And there we are again with the same discussion if custom implementation of protocol members, which have default implementation, should have the <code>override</code> keyword or not.</p>
<p>Imagine your code like this (not valid code):</p>
<pre><code>protocol Foo {
func bar()
}
extension Foo {
func bar() {
print("I am bar.")
}
}
class A : Foo {
func output() {
print(type(of:self))
default.bar() // fallback an call directly the default implementation whenever needed
self.bar() // will print "I am bar." on A().output() but should print "I am B." if Self == B
(self as! B).bar()
}
}
class B : A {
override func bar() {
print("I am B.")
}
}
</code></pre>
<p>I still think default implementations should be called through something like <code>default.</code> + whenever you override a default implementation you’d need <code>override</code>. There is a discussion going on: <code>Mark protocol methods with their protocol</code>. I clearly did not solved your issue, but I might have wake your interest to participate. ;)</p><span><font color="#888888">
<p></p></font></span></div><div><span><font color="#888888"><div style="font-family:Helvetica,Arial;font-size:13px;color:rgba(0,0,0,1.0);margin:0px;line-height:auto"><br></div> <br> <div><div style="font-family:helvetica,arial;font-size:13px">-- <br>Adrian Zubarev<br>Sent with Airmail</div></div></font></span><div><div> <br><p>Am 20. September 2016 um 04:13:22, Zhao Xin via swift-users (<a href="mailto:swift-users@swift.org" target="_blank">swift-users@swift.org</a>) schrieb:</p> </div></div><blockquote type="cite"><span><div><div></div><div><div><div>
<div dir="ltr">
<div class="gmail_default" style="font-family:georgia,serif">See
below code.</div>
<div class="gmail_default" style="font-family:georgia,serif">
<br></div>
<div class="gmail_default">
<p style="font-family:menlo;margin:0px;font-size:11px;line-height:normal;color:rgb(4,51,255)">
<span>protocol</span>
<span style="color:rgb(0,0,0)">Foo
{</span></p>
<p style="font-family:menlo;margin:0px;font-size:11px;line-height:normal">
<span>
</span> <span style="color:rgb(4,51,255)">func</span>
<span>bar()</span></p>
<p style="font-family:menlo;margin:0px;font-size:11px;line-height:normal">
<span>}</span></p>
<p style="font-family:menlo;margin:0px;font-size:11px;line-height:normal;min-height:13px">
<br></p>
<p style="font-family:menlo;margin:0px;font-size:11px;line-height:normal;color:rgb(4,51,255)">
<span>extension</span>
<span style="color:rgb(52,149,175)">Foo</span>
<span style="color:rgb(0,0,0)">{</span></p>
<p style="font-family:menlo;margin:0px;font-size:11px;line-height:normal">
<span>
</span> <span style="color:rgb(4,51,255)">func</span>
<span>bar()
{</span></p>
<p style="font-family:menlo;margin:0px;font-size:11px;line-height:normal;color:rgb(180,38,26)">
<span style="color:rgb(0,0,0)">
</span> <span style="color:rgb(52,149,175)">print</span><span style="color:rgb(0,0,0)">(</span><span>"I
am bar."</span><span style="color:rgb(0,0,0)">)</span></p>
<p style="font-family:menlo;margin:0px;font-size:11px;line-height:normal">
<span>
}</span></p>
<p style="font-family:menlo;margin:0px;font-size:11px;line-height:normal">
<span>}</span></p>
<p style="font-family:menlo;margin:0px;font-size:11px;line-height:normal;min-height:13px">
<br></p>
<p style="font-family:menlo;margin:0px;font-size:11px;line-height:normal">
<span style="color:rgb(4,51,255)">class</span>
<span>A:</span><span style="color:rgb(52,149,175)">Foo</span>
<span>{</span></p>
<p style="font-family:menlo;margin:0px;font-size:11px;line-height:normal">
<span>
</span> <span style="color:rgb(4,51,255)">func</span>
<span>output()
{</span></p>
<p style="font-family:menlo;margin:0px;font-size:11px;line-height:normal">
<span>
</span> <span style="color:rgb(52,149,175)">print</span><span>(type(of:</span><span style="color:rgb(4,51,255)">self</span><span>))</span>
<span style="color:rgb(0,143,0)">//
prints "B".</span></p>
<p style="font-family:menlo;margin:0px;font-size:11px;line-height:normal;color:rgb(0,143,0)">
<span style="color:rgb(0,0,0)">
</span> <span style="color:rgb(4,51,255)">self</span><span style="color:rgb(0,0,0)">.</span><span style="color:rgb(52,149,175)">bar</span><span style="color:rgb(0,0,0)">()</span>
<span>// prints
"I am bar."</span></p>
<p style="font-family:menlo;margin:0px;font-size:11px;line-height:normal">
<span>
(self</span> <span style="color:rgb(4,51,255)">as</span><span>!</span>
<span style="color:rgb(52,149,175)">B</span><span>).</span><span style="color:rgb(52,149,175)">bar</span><span>()</span>
<span style="color:rgb(0,143,0)">//
prints "I am B."</span></p>
<p style="font-family:menlo;margin:0px;font-size:11px;line-height:normal">
<span>
}</span></p>
<p style="font-family:menlo;margin:0px;font-size:11px;line-height:normal">
<span>}</span></p>
<p style="font-family:menlo;margin:0px;font-size:11px;line-height:normal;min-height:13px">
<br></p>
<p style="font-family:menlo;margin:0px;font-size:11px;line-height:normal">
<span style="color:rgb(4,51,255)">class</span>
<span>B:</span><span style="color:rgb(52,149,175)">A</span>
<span>{</span></p>
<p style="font-family:menlo;margin:0px;font-size:11px;line-height:normal">
<span>
</span> <span style="color:rgb(4,51,255)">func</span>
<span>bar()
{</span></p>
<p style="font-family:menlo;margin:0px;font-size:11px;line-height:normal">
<span>
</span> <span style="color:rgb(52,149,175)">print</span><span>(</span><span style="color:rgb(180,38,26)">"I
am B."</span><span>)</span></p>
<p style="font-family:menlo;margin:0px;font-size:11px;line-height:normal">
<span>
}</span></p>
<p style="font-family:menlo;margin:0px;font-size:11px;line-height:normal">
<span>}</span></p>
<p style="font-family:menlo;margin:0px;font-size:11px;line-height:normal;min-height:13px">
<br></p>
<p style="font-family:menlo;margin:0px;font-size:11px;line-height:normal">
<span style="color:rgb(4,51,255)">let</span>
<span>b =</span>
<span style="color:rgb(52,149,175)">B</span><span>()</span></p>
<p style="font-family:menlo;margin:0px;font-size:11px;line-height:normal;color:rgb(52,149,175)">
<span>b</span><span style="color:rgb(0,0,0)">.</span><span>output</span><span style="color:rgb(0,0,0)">()</span></p>
<p style="font-family:menlo;margin:0px;font-size:11px;line-height:normal;color:rgb(52,149,175)">
<br></p>
<p style="margin:0px;line-height:normal"><font color="#000000" face="georgia, serif">I thought `self.bar()` would do the same as
`(self as! B).bar()`. It didn't. In my opinion,
`type(of:self) is B.type`, so they should be the same,
shouldn't they?</font></p>
<p style="margin:0px;line-height:normal"><font color="#000000" face="georgia, serif"><br></font></p>
<p style="margin:0px;line-height:normal"><font color="#000000" face="georgia, serif">Zhaoxin</font></p>
</div>
</div></div></div>
______________________________<wbr>_________________<span><br>swift-users mailing list<br><a href="mailto:swift-users@swift.org" target="_blank">swift-users@swift.org</a><br><a href="https://lists.swift.org/mailman/listinfo/swift-users" target="_blank">https://lists.swift.org/mailma<wbr>n/listinfo/swift-users</a><br></span></div></div></span></blockquote></div><div><p></p></div></div><br></div></div>______________________________<wbr>_________________<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/mailma<wbr>n/listinfo/swift-evolution</a><br>
<br></blockquote></div><br></div>
<br>______________________________<wbr>_________________<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/mailma<wbr>n/listinfo/swift-evolution</a><br>
<br></blockquote></div><br></div>
</div></blockquote><blockquote type="cite"><div><span>______________________________<wbr>_________________</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/<wbr>mailman/listinfo/swift-<wbr>evolution</a></span><br></div></blockquote></div></div></div></blockquote></div><br></div>
</div></blockquote></body></html>