[swift-evolution] Bridging the gap between protocols and protocol extensions
Charles Srstka
cocoadev at charlessoft.com
Sat Jan 9 17:39:30 CST 2016
On Jan 9, 2016, at 4:05 PM, Brent Royal-Gordon via swift-evolution <swift-evolution at swift.org> wrote:
>
> From my previous thread, "[Draft Proposal] Require `final` on protocol extension members", I'm getting the sense that many people want straight-up dynamic dispatch from protocol extension methods. That is, protocol extension methods should be treated as if they were included as requirements of the protocol; the implementations provided should be treated as overridable defaults.
>
> A few questions about that:
>
> 1. Do people really want this?
I do. There are lots of useful things you could do with dynamically dispatched protocol extension methods that you cannot easily do elegantly. As an example, I could declare this extension on ErrorType:
extension ErrorType {
var isFileNotFoundError: Bool {
// Check for all of the possible “File not found” errors in POSIXError, NSCocoaError, NSURLError, NSOSStatusErrorDomain, etc.
// Then check for NSUnderlyingErrorKey and if it exists, rinse and repeat with that.
}
func toNSError() -> NSError {
return self as NSError
}
}
A method like this allows one to do things like this:
do {
try NSFileManager.defaultManager().removeItemAtURL(someURL)
} catch {
if error.isFileNotFoundError {
// The file we were trying to delete didn’t exist. Ignore the error
} else {
// Okay, something actually went wrong
NSApp.presentError(error.toNSError())
}
}
Then, perhaps you define your own error type that has a FileNotFound error condition in it, and would like to override these methods:
enum MyErrorType: ErrorType {
case FileNotFound(url: NSURL)
// more cases
var isFileNotFoundError: Bool {
// Unfortunately, this will never get called.
return case .FileNotFound(_) = self
}
func toNSError() -> NSError {
// This won’t get called either. The user will see a lovely “MyErrorType error (Int)” instead of our localized error message.
switch self {
case let .FileNotFound(url: url):
let userInfo = [NSLocalizedFailureReasonErrorKey : String(format: NSLocalizedString(“FNF %@“, comment: “String format: File Not Found error”), url.lastPathComponent)]
return NSError(domain: “MyErrorType”, code: 1, userInfo: userInfo)
// other cases
}
}
}
For any of the above to work as is, each and every error handler has to do an as? check against every custom error type in your project.
Charles
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160109/6ad17275/attachment.html>
More information about the swift-evolution
mailing list