Swift 超载??具有结果类型的运算符
我正在阅读并演示选项,第8章提到如何定义Swift 超载??具有结果类型的运算符,swift,Swift,我正在阅读并演示选项,第8章提到如何定义??运算符来处理结果类型,这是以前定义的类型。然而,当我尝试使用这个操作符时,我没有看到重载版本被调用。我是否错误地使用了此运算符 // Define ErrorType enum LookupError: ErrorType { case CapitalNotFound case PopulationNotFound } enum Result<T> { case Success(T) case Error(
??
运算符来处理结果类型,这是以前定义的类型。然而,当我尝试使用这个操作符时,我没有看到重载版本被调用。我是否错误地使用了此运算符
// Define ErrorType
enum LookupError: ErrorType {
case CapitalNotFound
case PopulationNotFound
}
enum Result<T> {
case Success(T)
case Error(ErrorType)
}
// Overloaded operator
func ??<T>(result: Result<T>, handleError: ErrorType -> T) -> T {
print("overloaded result: \(result)")
switch result {
case let .Success(value): return value
case let .Error(error): return handleError(error)
}
}
但是重载运算符在任何时候都不会被调用。您的
r
是一个结果
包装在一个可选的中,因此您得到了适用于可选的??运算符的版本
由于您在示例中没有使用可选性,因此只需修改声明:
let r:Result<String> = Result<String>.Success("A-Ok")
let d = Result<String>.Success("Error")
let result = r ?? d
让r:Result=Result.Success(“A-Ok”)
设d=Result.Success(“Error”)
设结果=r??D
你是表达式让结果=r??d
与重载的函数签名不匹配,因此它不知道您要调用的是您的函数(而是调用常规的nil合并运算符)
让我们看看签名:
func ??<T>(result: Result<T>, handleError: ErrorType -> T) -> T { ...
现在,为了在调用函数签名时与函数签名一致,我们将表达式的右侧构造为闭包,如下所示:
var result = r ?? {
err in
switch err as! LookupError {
case .CapitalNotFound: return "Couldn't find capital"
case .PopulationNotFound: return "Couldn't find population"
}
}
print(result) /* A-Ok */
result = d ?? {
err in
switch err as! LookupError {
case .CapitalNotFound: return "Couldn't find capital"
case .PopulationNotFound: return "Couldn't find population"
}
}
print(result) /* Couldn't find capital */
好的,现在我们实际上称你的?
重载。然而,上面的这些表达式看起来相当混乱,特别是如果我们想频繁调用自定义的?
操作符
与每次执行错误检查时都发布相同的闭包不同,我们可以为闭包创建一个句柄来代替它。句柄与上面的闭包一样,在调用自定义??运算符时用作右侧参数:
func myStringErrHandler () -> (ErrorType -> String) {
return { (err: ErrorType) -> (String) in
switch err as! LookupError {
case .CapitalNotFound: return "Couldn't find capital"
case .PopulationNotFound: return "Couldn't find population"
}
}
let errHandle = myStringErrHandler()
var result = r ?? errHandle
print(result) /* A-Ok */
result = d ?? errHandle
print(result) /* Couldn't find capital */
这可能会做得更整洁,但您明白了要点:我们必须确保调用及其参数符合自定义函数的签名 d
此处不符合预期的ErrorType->String
闭包,即自定义??
函数中的第二个参数(rhs)。因此,这将不会调用自定义的?
函数。啊,很好。我只讨论了第一个参数类型的问题,但需要解决两个方面的问题。我被Swift对nil合并运算符的定义甩了,它的定义如下:public func??(可选:T?,@autoclosure defaultValue:()throws->T)rethrows->T defaultValue参数看起来像是接受了一个没有任何参数的函数,返回了一个类型为T的值。由于Swift lang版本没有接受函数,我假设上面的版本也不会接受。您是对的,对于本机??
案例,第二个参数是闭包,即使它看起来可以像是T
类型的单个参数一样使用。这里的关键是关键字@autoclosure
,它允许不带任何参数的闭包函数参数作为参数发送到函数,而不必包装在{…}
中。因此,在本机?
,rhs
中lhs??rhs
实际上描述了闭包的return语句()->T
(您可以将其视为lhs???{return rhs}
)。原因是我们可以懒散地评估rhs
(因为它是一个闭包)。。。。。。因为如果我们选择的话,rhs
(闭包返回值)的实际值只会在函数?
中“评估”:我们只希望在lhs
包含nil
的情况下如此。因此(抛开错误不谈),对于本机?
,我们还可以将第二个参数定义为标准的单变量参数,但这样就不会对进行延迟计算,如果我们永远无法到达nil合并表达式的右侧,这将是浪费。有点过时,但对学习仍然有用,请参见:
var r:Result<String> = Result<String>.Success("A-Ok")
var d:Result<String> = Result<String>.Error(LookupError.CapitalNotFound)
var result = r ?? {
err in
switch err as! LookupError {
case .CapitalNotFound: return "Couldn't find capital"
case .PopulationNotFound: return "Couldn't find population"
}
}
print(result) /* A-Ok */
result = d ?? {
err in
switch err as! LookupError {
case .CapitalNotFound: return "Couldn't find capital"
case .PopulationNotFound: return "Couldn't find population"
}
}
print(result) /* Couldn't find capital */
func myStringErrHandler () -> (ErrorType -> String) {
return { (err: ErrorType) -> (String) in
switch err as! LookupError {
case .CapitalNotFound: return "Couldn't find capital"
case .PopulationNotFound: return "Couldn't find population"
}
}
let errHandle = myStringErrHandler()
var result = r ?? errHandle
print(result) /* A-Ok */
result = d ?? errHandle
print(result) /* Couldn't find capital */