ios - Swift 面向协议(protocol)的扩展

标签 ios swift protocols swift-protocols protocol-oriented

试图了解 Swift 中面向协议(protocol)的编程以及扩展如何工作以及它可以提供什么级别的可扩展性。

有以下我在 Playgrounds 中运行的代码片段

protocol ProtocolA {
    func doSomethingA()
}

protocol ProtocolB {
    func doSomethingB()
}

protocol ProtocolC {
    func doSomethingC()
}

extension ProtocolA {
    func doSomethingA() {
        print("Extension - doSomethingA")
    }
}

extension ProtocolA where Self: ProtocolB {
    func doSomethingA() {
        print("Extension - doSomethingA Self: ProtocolB")
    }
}

extension ProtocolA where Self: ProtocolC {
    func doSomethingA() {
        print("Extension - doSomethingA Self: ProtocolC")
    }
}

extension ProtocolA where Self: ProtocolB, Self: ProtocolC {
    func doSomethingA() {
        print("Extension - doSomethingA Self: ProtocolB, ProtocolC")
    }
}

extension ProtocolB {
    func doSomethingB() {
        print("Extension - doSomethingB")
    }
}

extension ProtocolC {
    func doSomethingC() {
        print("Extension - doSomethingC")
    }
}

class Implementation: ProtocolA, ProtocolB, ProtocolC {
}

let obj = Implementation()

obj.doSomethingA()

我打印的是:

Extension - doSomethingA Self: ProtocolB, ProtocolC

无论如何我可以保证所有的扩展都能运行。

理想情况下,我希望获得以下输出。

Extension - doSomethingA
Extension - doSomethingA Self: ProtocolB
Extension - doSomethingA Self: ProtocolC
Extension - doSomethingA Self: ProtocolB, ProtocolC

我知道 Swift 会根据类型选择最强的匹配项,事实上,如果我不提供 ProtocolA 同时匹配 ProtocolB 和 ProtocolC 的实现,我会遇到编译时错误。无论如何,我可以解决这个问题吗?

谢谢。

最佳答案

扩展的目的是为协议(protocol)方法提供一个默认实现

在您的示例中,编译器将决定调用最适合您的具体对象的扩展的 doSomethingA() 方法,仅此而已。

正如您在通话中看到的那样:

obj.doSomethingA()

您正在执行一个 方法调用。这将被解析并分派(dispatch)给一个方法调用,而不是四个。

这类似于通过子类重写方法并调用基类的方法时,只调用派生方法而不调用基类方法。在这种情况下,如果您愿意,可以从子类中调用 super.method()

在您的情况下,如果您希望调用多个方法,您可以通过扩展为它们提供单独的名称和实现,然后只需创建一个实现所有协议(protocol)的类,如下所示:

class A: ProtocolA, ProtocolB, ProtocolC {

   func all() {
      doSomethingA()
      doSomethingB()
      doSomethingC()
   }
}

此处扩展的优点是您的 class A 不必为这三个方法提供实现。

关于ios - Swift 面向协议(protocol)的扩展,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38161761/

相关文章:

ios - 如何使用来自 webservice 的字符串数组到 INSPhotoViewable

ios - 在 iOS 11 中编辑文本字段时 uitableViewCell 不向上滚动

ios - 如何以编程方式取消 iOS 中的滑动删除操作?

swift - 从网络服务更新核心数据。 (插入/更新/删除)

ios - 切换 View 时如何使 UISearchController 处于非事件状态

IOS - 无法在应用程序的根目录加载图像

swift - 如何使用 Vapor (流畅迁移)将字段从必需更新为可选?

ios - 使用协议(protocol)接收消息?

swift - 在 Swift 中,为什么子类方法不能覆盖父类(super class)中协议(protocol)扩展提供的方法

python - 快速开发路由协议(protocol)原型(prototype)的环境