如何在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。
  • 你必須始終經過可選地調用或檢查符合類型是否實現它來檢查是否實現了可選方法。若是您常常調用可選方法,這可能會引入不少冗餘代碼。

原文連接

相關文章
相關標籤/搜索