面向Swift协议的扩展

时间:2016-07-02 15:36:06

标签: ios swift protocols swift-protocols protocol-oriented

试图了解Swift中面向协议的编程以及扩展如何工作以及它可以提供的可扩展性。

我有以下代码片段,我通过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匹配的实现,我会得到一个编译时间错误。无论如何我可以绕过这个吗?

感谢。

1 个答案:

答案 0 :(得分:2)

扩展点是为协议方法提供默认实现

在您的示例中,编译器将决定调用最适合您具体对象的扩展的doSomethingA()方法,但那就是它。

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

obj.doSomethingA()

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

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

在你的情况下,如果你想要调用多个方法,你可以通过扩展为它们分别提供名称和实现,然后创建一个实现所有协议的类,如下所示:

class A: ProtocolA, ProtocolB, ProtocolC {

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

此处扩展程序的优势在于您的class A不必为这三种方法提供实现。