一尘不染

如何在Swift协议中定义可选方法?

swift

在Swift中有可能吗?如果没有,那么是否有解决方法?


阅读 291

收藏
2020-07-07

共1个答案

一尘不染

1.使用默认实现(首选)。

protocol MyProtocol {
    func doSomething()
}

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

struct MyStruct: MyProtocol {
    /* no compile error */
}

优点

  • 不涉及Objective-C运行时 (至少没有明确 涉及 )。这意味着您可以NSObject使其符合结构,枚举和非类。同样,这意味着您可以利用强大的泛型系统。

  • *当遇到符合此类协议的类型时, *您始终可以确保满足所有要求 。它始终是具体实现或默认实现。这就是“接口”或“合同”在其他语言中的行为方式。

缺点

  • 对于非Void要求,您需要具有一个合理的默认值,但这并非总是可能的。但是,当您遇到此问题时,这意味着该要求实际上应该没有默认实现,或者您在API设计期间犯了一个错误。

  • 您无法区分默认实现和根本没有实现 ,至少没有用特殊的返回值解决该问题。考虑以下示例:

    protocol SomeParserDelegate {
    func validate(value: Any) -> Bool
    

    }

如果您提供仅返回的默认实现true-乍一看就可以了。现在,考虑以下伪代码:

    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 */
        }
    }
}

无法实现这种优化-您不知道委托是否实现了一种方法。

尽管有多种方法可以解决此问题(使用可选的闭包,针对不同的操作使用不同的委托对象,仅举几例),但该示例清楚地提出了问题。


2.使用@objc optional

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

class MyClass: NSObject, MyProtocol {
    /* no compile error */
}

优点

  • 无需默认实现。 您只需声明一个可选方法或变量,就可以使用了。

缺点

  • 要求所有符合类型都必须与Objective-C兼容 ,从而严重限制了协议的功能 。这意味着,仅继承自NSObject该类的类可以遵循此类协议。没有结构,没有枚举,没有关联的类型。

  • 您必须始终 通过可选调用或检查符合类型 是否实现了可选方法来检查是否实现了可选方法 。如果您经常调用可选方法,这可能会引入很多样板。

2020-07-07