ios - 具有父类(super class)和子类的 Swift 协议(protocol)扩展方法分派(dispatch)

标签 ios swift protocols protocol-extension

我发现了一个有趣的行为,它看起来像是一个错误......

基于以下文章描述的行为:

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)时,输出不是我所期望的。

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

您知道这是错误还是设计使然?一位同事建议,混合继承和协议(protocol)扩展可能无法按预期工作。我打算使用协议(protocol)扩展来提供默认实现...如果我做不到,那么遗憾的是我将不得不将其标记为 @objc 并返回到可选协议(protocol)。

最佳答案

来自帖子 The Ghost of Swift Bugs Future ,这是帖子末尾提到的协议(protocol)扩展的调度规则。

  1. 如果变量的推断类型是协议(protocol):
  2. AND 该方法在原始协议(protocol)中定义,然后 调用运行时类型的实现,无论是否 扩展中有一个默认实现。
  3. 并且该方法未在原始协议(protocol)中定义,然后 调用默认实现。
  4. ELSE IF 变量的推断类型是该类型 THEN 调用该类型的实现。

所以在你的情况下,你是说 method1() 是在协议(protocol)中定义的,并且已经在子类中实现了。但是你的父类(super class)正在采用协议(protocol)但它没有实现 method1() 并且子类只是继承自父类(super class)并且不直接采用协议(protocol)。这就是为什么我相信这就是当您调用 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() 

那么这个错误(这似乎是一个错误)的解决方法是,您需要在父类(super class)中实现协议(protocol)方法,然后您需要覆盖子类中的协议(protocol)方法。

关于ios - 具有父类(super class)和子类的 Swift 协议(protocol)扩展方法分派(dispatch),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34847318/

相关文章:

ios - RX Swift - API 的并行执行

ios - 如何在不使用 Storyboard的情况下创建通知内容扩展

ios - 如何在 swift 2 中从 tableView 中清除已删除的 TableView 单元格

ios - 在 Swift 中使用协议(protocol)和委托(delegate)将数据从 UITableViewDataSource 传递到 UIViewController

ios - UITableViewCell - 隐藏未使用的 View 或什至不添加它们?

ios - 从 url 下载 pdf 文件

ios - 一般问题,有什么建议吗?

swift - 使用观察者模式设置委托(delegate)时遇到问题

ios - 在 iOS 应用程序中存储用户名和密码的正确方法

ios - 如果我支持 iOS 3.x,Apple 会拒绝我们的应用程序吗?