Swift'open'关键字和可重写的方法/属性的扩展名?

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

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

public模块/框架之间扩展的publicclass )方法/属性的代码被破坏,因为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" } } 
  • 原始提案( SE-0117 )主要关注子类,并没有提及扩展。
  • 目前的扩展不支持open关键字(你不能写open extension NSObject以及open func Method()

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

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

 extension UIManagedDocument { open class func primaryDocumentName() -> String { return "Document" } // ... } 

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

 class MyManagedDocument: UIManagedDocument { override class func primaryDocumentName() -> String { return "MyDocument" } // ... } 
  • “面向协议 ” – 用所需的方法/属性声明协议 ,然后重构您的扩展以实现协议遵从性。
  • “传统” – 实现具有所需方法/属性的中间(抽象)子类。

协议示例:

 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" } }