Swift'open'关键字和可重写的方法/属性的扩展名?
在Swift 3.0中引入了open
关键字(Swift 中的'open'关键字是什么?
注意:仅限于NSObject
派生类或@objc
属性方法/属性的扩展。
在public
模块/框架之间扩展的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" } }
- 原始提案( 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" } }