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.

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.
> Extending Interfaces That Contain Default Methods
> 
> When you extend an interface that contains a default method, you can do the 
> following:
> 
> Not mention the default method at all, which lets your extended interface 
> inherit the default method.
> Redeclare the default method, which makes it abstract.
> Redefine the default method, which overrides it.

https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html

I am not sure why protocol extension need to differ so much and present 
dispatch rules that are potentially very confusing. 

Casting at runtime should *never* change what implementation of a method gets 
called. 
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.

Sent from my iPhone

> On 20 Sep 2016, at 16:18, Nevin Brackett-Rozinsky via swift-evolution 
> <swift-evolution@swift.org> wrote:
> 
> I think there is a deeper issue that may be worth exploring here.
> 
> 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.
> 
> 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()”.
> 
> 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”.
> 
> 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.
> 
> 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.
> 
> 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*:
> 
> 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()”).
> 
> 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.
> 
> Nevin
> 
> 
> 
>> On Tue, Sep 20, 2016 at 8:01 AM, Zhao Xin via swift-evolution 
>> <swift-evolution@swift.org> wrote:
>> Thank you to  Игорь Никитин and Adrian Zubarev. Now I can convince myself 
>> for this behavior.
>> 
>> As Adrian's example shows, there is no `bar()` implemented in `class A`, so 
>> there is no `override func bar()` in class B`. My thought that  `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.
>> 
>> The behavior is clear now. In class A's `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.
>> 
>> Zhaoxin
>> 
>>> On Tue, Sep 20, 2016 at 4:21 PM, Adrian Zubarev via swift-evolution 
>>> <swift-evolution@swift.org> wrote:
>>> I can’t tell you the reason, but to me it feels like it’s doing the 
>>> following thing:
>>> 
>>> + - - (Type: B) - - +
>>> |                   |
>>> | func bar()    + - + (Type: A) - - +                        < - - - - - - 
>>> - - - - - - - - - - - - - - +
>>> |               |                   |                                       
>>>                            |
>>> + - - - - - - - + func output() + - + (Protocol: Foo) - - +  — - self.bar() 
>>> - + - (self as! B).bar() - +
>>>                 |               |                         |                 
>>>   |
>>>                 + - - - - - - - + (default) func bar()    |  <- - - - - - - 
>>> - +
>>>                                 |                         |
>>>                                 + - - - - - - - - - - - - +
>>> 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.")
>>>     }
>>> }
>>> Would solve this temporarily.
>>> 
>>> And there we are again with the same discussion if custom implementation of 
>>> protocol members, which have default implementation, should have the 
>>> override keyword or not.
>>> 
>>> Imagine your code like this (not valid 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.")
>>>     }
>>> }
>>> I still think default implementations should be called through something 
>>> like default. + whenever you override a default implementation you’d need 
>>> override. There is a discussion going on: Mark protocol methods with their 
>>> protocol. I clearly did not solved your issue, but I might have wake your 
>>> interest to participate. ;)
>>> 
>>> 
>>> 
>>> -- 
>>> Adrian Zubarev
>>> Sent with Airmail
>>> 
>>> Am 20. September 2016 um 04:13:22, Zhao Xin via swift-users 
>>> (swift-us...@swift.org) schrieb:
>>> 
>>>> See below code.
>>>> 
>>>> protocol Foo {
>>>>     func bar()
>>>> }
>>>> 
>>>> extension Foo {
>>>>     func bar() {
>>>>         print("I am bar.")
>>>>     }
>>>> }
>>>> 
>>>> class A:Foo {
>>>>     func output() {
>>>>         print(type(of:self)) // prints "B".
>>>>         self.bar() // prints "I am bar."
>>>>         (self as! B).bar() // prints "I am B."
>>>>     }
>>>> }
>>>> 
>>>> class B:A {
>>>>     func bar() {
>>>>         print("I am B.")
>>>>     }
>>>> }
>>>> 
>>>> let b = B()
>>>> b.output()
>>>> 
>>>> 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?
>>>> 
>>>> Zhaoxin
>>>> _______________________________________________
>>>> swift-users mailing list
>>>> swift-us...@swift.org
>>>> https://lists.swift.org/mailman/listinfo/swift-users
>>> 
>>> 
>>> _______________________________________________
>>> 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

Reply via email to