Extended protocol propagation method with superclass and subclass

I found an interesting behavior that seems to be a mistake ...

Based on the described behavior, the following articles are described:

https://medium.com/ios-os-x-development/swift-protocol-extension-method-dispatch-6a6bf270ba94

http://nomothetis.svbtle.com/the-ghost-of-swift-bugs-future

The result is not what I expect when I add SomeSuperclass , and not directly accept the protocol.

 protocol TheProtocol { func method1() } extension TheProtocol { func method1() { print("Called method1 from protocol extension") } func method2NotInProtocol() { print("Called method2NotInProtocol from protocol extension") } } // This is the difference - adding a superclass class SomeSuperclass: TheProtocol { } // It works as expected when it simply adopts TheProtocol, but not when it inherits from a class that adopts the protocol class MyClass: SomeSuperclass { func method1() { print("Called method1 from MyClass implementation") } func method2NotInProtocol() { print("Called method2NotInProtocol from MyClass implementation") } } let foo: TheProtocol = MyClass() foo.method1() // expect "Called method1 from MyClass implementation", got "Called method1 from protocol extension" foo.method2NotInProtocol() // Called method2NotInProtocol from protocol extension 

Do you know that this is a mistake or design? One colleague suggested that mixing inheritance and protocol extensions might not work as expected. I was going to use the protocol extension to provide a default implementation ... if I cannot do this, then, unfortunately, I will have to mark it with @objc and return to the optional protocol.

+7
ios swift protocols
source share
2 answers

From the โ€œPhantom of the fast mistakes of the futureโ€ message, here are the sending rules for protocol extensions that are mentioned at the end of the message.

  • IF the selected variable type is a protocol:
  • And the method is defined in the original THEN protocol. implementation of run-time types, regardless of whether the extension has a default implementation.
  • And the method is not defined in the original protocol, then the default implementation is called.
  • ELSE If the derived variable type is a THEN type, the type implementation is called.

So, in your state, you say that method1 () is defined in the protocol and implemented in a subclass. But your superclass uses the protocol, but does not implement the 1 () method, and the subclass simply inherits from the superclass and does not directly accept the protocols. Therefore, I believe that this is the reason you call foo.method1 (), it does not call the implementation of the subclass, as described in paragraphs 1 and 2.

But when you do it,

 class SomeSuperclass: TheProtocol { func method1(){ print("super class implementation of method1()")} } class MyClass : SomeSuperclass { override func method1() { print("Called method1 from MyClass implementation") } override func method2NotInProtocol() { print("Called method2NotInProtocol from MyClass implementation") } } 

and then when you call

  let foo: TheProtocol = MyClass() foo.method1() // Called method1 from MyClass implementation foo.method2NotInProtocol() 

So what could be a workaround for this error (which seems to be an error) is that you need to implement the protocol method in the superclass, and then you need to override the protocol method in the subclass. NTN

+1
source share

Please check the code below:

 import UIKit protocol TheProtocol { func method1() func method2NotInProtocol() } extension NSObject { func method1() { print("Called method1 from protocol extension") } func method2NotInProtocol() { print("Called method2NotInProtocol from protocol extension") } } // This is the difference - adding a superclass class SomeSuperclass :NSObject, TheProtocol { override func method1() { print("Called method1 from SomeSuperclass implementation") } } // It works as expected when it simply adopts TheProtocol, but not when it inherits from a class that adopts the protocol class MyClass : SomeSuperclass { override func method1() { print("Called method1 from MyClass implementation") } override func method2NotInProtocol() { print("Called method2NotInProtocol from MyClass implementation") } } let foo: TheProtocol = MyClass() foo.method1() // expect "Called method1 from MyClass implementation", got "Called method1 from protocol extension" foo.method2NotInProtocol() // Called method2NotInProtocol from protocol extension 

Instead of writing the extension in TheProtocol, write the extension in an abstract class (NSObject in the code above). This works as expected.

0
source share

All Articles