问题
With introduction of open
keyword in Swift 3.0 (What is the 'open' keyword in Swift?).
Note: Limited to extensions on NSObject
derived classes or @objc
attributed method/properties.
Code wich declared and used public
(class
) methods/properties in extension across modules/frameworks broke, as public
is no longer means 'overridable' outside of defining module.
Example:
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"
}
}
- Original proposal (SE-0117) is focused on subclassing and doesn't mention extensions.
- Currently extensions do not support
open
keyword (you can't writeopen extension NSObject
as well asopen func Method()
)
Question: Is there workaround to be able override extension provided methods/properties across modules/frameworks?
回答1:
Unless I am mistaken, you can declare the extension methods as
open
in your framework if you just omit the public
keyword
in the extension declaration:
extension UIManagedDocument {
open class func primaryDocumentName() -> String {
return "Document"
}
// ...
}
And then (for NSObject
subclasses or @objc
members) you can override the method
in your custom subclass in the main application (or in any module):
class MyManagedDocument: UIManagedDocument {
override class func primaryDocumentName() -> String {
return "MyDocument"
}
// ...
}
回答2:
- 'Protocol-oriented' - declare protocol with desired methods/properties then refactor your extension for protocol compliance.
- 'Traditional' - implement intermediate (abstract) subclass with desired methods/properties.
Protocol example:
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"
}
}
来源:https://stackoverflow.com/questions/39141975/swift-open-keyword-overridable-method-properties-in-extension