如何在Swift的Protocol中定义可选方法(译)

使用默认实现(推荐)

protocol MyProtocol {
    func doSomething()
}

extension MyProtocol {
    func doSomething() {
        /* return a default value or just leave empty */
    }
}

struct MyStruct: MyProtocol {
    /* no compile error */
}
复制代码

优点

  • 没有牵扯到OC的runtime(至少没有明显的用到)。这就意味着你的structs、enum、或者非继承自NSObject的class去遵照它。此外,你还可使用功能强大的泛型(generics) 。对泛型不了解的,能够经过这篇文章来了解泛型的基本使用。
  • 当遇到符合此类protocol的类型时,你能够确保知足全部要求。它始终是具体实现或默认实现,这就至关于其余语言的“interfaces”或“contracts”的做用。

劣势

  • 对于有返回值的函数,你须要返回一个合适的默认值,这并不老是可行的。可是,当你遇到了这个问题,就说明这个函数不该该声明为可选的,或者你在设计API的时候犯错了。
  • 你没法区分是提供了一个默认的实现,仍是并无实现。至少没有一个特殊的返回值来解决该问题。看一下下面的代码:
protocol SomeParserDelegate {
    func validate(value: Any) -> Bool
}
复制代码

若是你提供了一个返回值为true的默认实现,乍一看这么作没有问题。接下来考虑一下下面的伪代码:swift

final class SomeParser {
    func parse(data: Data) -> [Any] {
        if /* delegate.validate(value:) is not implemented */ {
            /* parse very fast without validating */
        } else {
            /* parse and validate every value */
        }
    }
}
复制代码

这时是没法实现优化这个分支(if)的,由于你没法知道你的delegate是否实现了这个方法。 虽然有不少方法能够解决这个问题(使用optional closures,不一样的delegate对象用于不一样的操做等等),这个例子只是清晰地说明这么作存在的问题。bash

使用@objc optional

@objc protocol MyProtocol {
    @objc optional func doSomething()
}

class MyClass: NSObject, MyProtocol {
    /* no compile error */
}
复制代码

优点

  • 不须要默认实现,经过@objc optional 关键字修饰就能够了。

劣势

  • 这样只能是符合OC中遵照protocol的类型,才能遵照该protocol,这样严重限制了Protocol的功能。这就意味着只有继承自NSObject的类才能遵照该协议。struct、enum都不行,也不能使用associated type。
  • 你必须始终经过可选地调用或检查符合类型是否实现它来检查是否实现了可选方法。若是您常常调用可选方法,这可能会引入不少冗余代码。

原文连接

相关文章
相关标签/搜索