扩展中的Swift'open'关键字和可覆盖的方法/属性?

Noc*_*oss 10 syntax ios swift swift-extensions

open在Swift 3.0中引入了关键字(Swift 中的'open'关键字是什么?).

注意:仅限于NSObject派生类或@objc属性方法/属性的扩展.

模块/框架的扩展中声明和使用public(class)方法/属性的代码破坏了,因为在定义模块之外不再意味着"可覆盖".public

例:

public extension UIManagedDocument {

    public class func primaryDocumentName() -> String {
        return "Document"
    }

    public class func primaryStoreURL() -> URL {
        let documentsURL = FileManager.default.userDocumentsURL
        return URL(fileURLWithPath: self.primaryDocumentName(), isDirectory: false, relativeTo: documentsURL)
    }

    public class func primaryModelName() -> String? {
        return "Model"
    }

}
Run Code Online (Sandbox Code Playgroud)
  • 原始提案(SE-0117)侧重于子类化,并未提及扩展.
  • 目前扩展不支持open关键字(你不能写得open extension NSObject那么好open func Method())

问题:是否有解决方案能够模块/框架覆盖扩展提供的方法/属性?

Mar*_*n R 8

除非我弄错了,如果你只是省略扩展声明中的关键字,你可以open在框架中声明扩展方法 public:

extension UIManagedDocument {

    open class func primaryDocumentName() -> String {
        return "Document"
    }
    // ...
}
Run Code Online (Sandbox Code Playgroud)

然后(对于NSObject子类或@objc成员),您可以在主应用程序(或任何模块)中覆盖自定义子类中的方法:

class MyManagedDocument: UIManagedDocument {

    override class func primaryDocumentName() -> String {
        return "MyDocument"
    }
    // ...
}
Run Code Online (Sandbox Code Playgroud)


Noc*_*oss 3

  • “面向协议”-使用所需的方法/属性声明协议,然后重构您的扩展以实现协议合规性。
  • “传统”- 使用所需的方法/属性实现中间(抽象)子类。

协议示例:

protocol PrimaryDocument {
    static func primaryDocumentName() -> String

    static func primaryStoreURL() -> URL

    static func primaryModelName() -> String?
}

extension UIManagedDocument : PrimaryDocument {

    open class func primaryDocumentName() -> String {
        return "Document"
    }

    open class func primaryStoreURL() -> URL {
        let documentsURL = FileManager.default.userDocumentsURL
        return URL(fileURLWithPath: self.primaryDocumentName(), isDirectory: false, relativeTo: documentsURL)
    }

    open class func primaryModelName() -> String? {
        return "Model"
    }

}
Run Code Online (Sandbox Code Playgroud)