<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body 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="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&nbsp;<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">https://docs.oracle.com/javase/tutorial/java/IandI/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.&nbsp;</div><div style="direction: inherit;"><br></div><div style="direction: inherit;">Casting at runtime should *never* change what implementation of a method gets called.&nbsp;</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><br>On 20 Sep 2016, at 16:18, Nevin Brackett-Rozinsky via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>&gt; 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">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;</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 &nbsp;Игорь Никитин and&nbsp;Adrian Zubarev. Now I can convince myself for this&nbsp;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&nbsp;</span><span style="color:rgb(0,0,0);font-family:georgia,serif;font-size:13px">&nbsp;</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 class="h5">On Tue, Sep 20, 2016 at 4:21 PM, Adrian Zubarev via swift-evolution <span dir="ltr">&lt;<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>&gt;</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 class="h5"><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) - - +                        &lt; - - - - - - - - - - - - - - - - - - - - +
|               |                   |                                                                  |
+ - - - - - - - + func output() + - + (Protocol: Foo) - - +  — - self.bar() - + - (self as! B).bar() - +
                |               |                         |                   |
                + - - - - - - - + (default) func bar()    |  &lt;- - - - - - - - +
                                |                         |
                                + - - - - - - - - - - - - +
</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">--&nbsp;<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>&nbsp;
&nbsp;</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>&nbsp;
&nbsp;</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)">&nbsp;
&nbsp; &nbsp; &nbsp;</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>&nbsp;
&nbsp; }</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>&nbsp;
&nbsp;</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>&nbsp;
&nbsp; &nbsp; &nbsp;</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)">&nbsp;
&nbsp; &nbsp; &nbsp;</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>&nbsp;
&nbsp; &nbsp; &nbsp; (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>&nbsp;
&nbsp; }</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>&nbsp;
&nbsp;</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>&nbsp;
&nbsp; &nbsp; &nbsp;</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>&nbsp;
&nbsp; }</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,
&nbsp;`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">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/<wbr>mailman/listinfo/swift-<wbr>evolution</a><br>
<br></blockquote></div><br></div>
</div></blockquote><blockquote type="cite"><div><span>_______________________________________________</span><br><span>swift-evolution mailing list</span><br><span><a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a></span><br><span><a href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a></span><br></div></blockquote></body></html>