Swift协议扩展方法分派与超类和子类

我发现了一个有趣的行为,这似乎是一个错误…

根据以下文章描述的行为:

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

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

输出不是我所期望的,当我添加SomeSuperclass ,而不是直接采用协议。

 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 

你知道这是一个错误还是devise? 一位同事build议,混合inheritance和协议扩展可能无法按预期工作。 我打算使用协议扩展来提供一个默认的实现…如果我不能这样做,那么我将不得不将它标记为@objc并返回到一个可选的协议。

从“ Swift Bugs Future ”的“鬼魂”这篇文章可以看出, 这篇文章最后提到了协议扩展的规则。

  1. 如果variables的推断types是协议:
  2. 并且该方法在原始协议中定义,则调用运行时types的实现,而不pipe扩展中是否有默认实现。
  3. 并且该方法没有在原始协议中定义,那么调用默认实现。
  4. ELSE如果variables的推断types是THENtypes,则调用该types的实现。

所以在你的情况下,你说method1()是在协议中定义的,并且已经在子类中实现了。 但是你的超类正在采用协议,但是它并没有实现方法1()和子类只是从超类inheritance而来,并没有直接采用协议。 这就是为什么我相信这是你调用foo.method1()的原因,它不会像点1和2所述那样调用子类的实现。

但是,当你这样做,

 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") } } 

然后当你打电话,

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

那么这个bug的解决方法是什么(这似乎是一个bug),就是你需要在超类中实现协议方法,然后你需要重写子类中的协议方法。 HTH

请检查下面的代码:

 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 

而不是写扩展到TheProtocol,写扩展到一个抽象类(NSObject在上面的代码)。 这按预期工作。