考虑以下功能:
func myFunction(completion: (data: Data?,error: Error?) -> ()) { }
我目前的要求是完成:只接受数据值或错误值,但不接受两者.一个人必须是零.
很容易将它们保持为可选,然后展开并稍后检查它们的值,但我认为如果编译器能够通知开发人员他们不能同时设置它们会更好.
从另一个角度来看,知道其中一个将总是设置为someValue会更有用.
通过这种方式,您可以保证您将收到错误或数据,并且永远不必担心处理它们都是零的情况.
目前有办法做到这一点吗?
解决方法
你想要一些它无法做到的Swift.特别是,据我所知,Swift没有联合类型.如果你想要这样的东西,你可能想看看功能性或功能性的语言.
插曲:如果两种类型都是结构或类(即非协议),则可以使用此模式:
protocol DataOrError {} extension Data: DataOrError {} extension ErrorClass: DataOrError {}
假设没有协议的其他实现者,您现在有一些接近联合类型的东西.您也可以切换大小写类型:
switch doe { case let e as Error: print("Error \(e)") case let d as Data: print("Data \(d)") default: assert(false,"thou shalt not implement my dummy!") }
无论如何,我们可以使用带有相关值的枚举来伪造它,这可以(有限制地)用作穷人的联合类型.
定义这样的枚举:
enum DataOrError { case Data(Data) case Error(Error) }
现在您可以使用DataOrError,您可以(确切地)拥有Data或Error以及DataOrError之一吗?至多一个.
来电网站,您可以得到以下内容:
extension String: Error {} // low-effort errors,don't judge me! func myFunction(completion: (DataOrError) -> ()) { completion(.Data(Data(bytes: [1,2,3,4,5]))) completion(.Error("this won't work!")) }
和被叫网站:
var myCompletion = { (doe: DataOrError) in switch doe { case .Data(let d): print("Data \(d)") case .Error(let e): print("Error \(e)") } } myFunction(completion: myCompletion) // > Data 5 bytes // > Error this won't work!
设计说明:您可能正在寻找另一个方向的概括,特别是如果您有许多不同类型的OR或Error.在这种情况下,即使您牺牲了良好的语法,显式包装器也可能是一个很好的解决方案.
struct TalkativeOptional<T> { private(set) var rawValue: T? private(set) var error: Error? init(value: T) { self.rawValue = value } init(error: Error) { self.error = error } }
请注意两个属性中的一个属性是否为非零.还有两种组合;在这里,您可以通过选择初始化程序来控制所需的内容.
示例callee-site:
func convert(_ number: String) -> TalkativeOptional<Int> { if let int = Int(number) { return TalkativeOptional(value: int) } else { return TalkativeOptional(error: "'\(number)' not a valid integer!") } }
var a = convert("dsa2e2") if let val = a.rawValue { print("a + 1 = \(val + 1)") } else { // we kNow by design that error is set! print("ERROR: \(a.error!)") }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。