如何声明重抛函数?附布尔数组扩展抛错函数实现代码
如何将Swift函数声明为重抛函数?
看起来你想把自己实现的indexOfFirstTrue()改成重抛(rethrows)函数,不过得先理清Swift中rethrows的核心逻辑——重抛函数并不是“自己抛出错误”的函数,而是只会传递闭包参数抛出的错误的函数。我来一步步给你讲清楚怎么处理:
先搞懂rethrows的适用场景
rethrows关键字只能用在满足以下条件的函数上:
- 函数至少接受一个可能抛出错误的闭包参数
- 函数本身不会主动抛出自定义错误,只会把闭包参数抛出的错误“重新抛出”
- 如果传入的闭包没有抛出错误,整个函数也不会抛出错误
你的现有函数是主动抛出CustomError的,而且没有闭包参数,所以直接把throws改成rethrows会触发编译器报错——不符合重抛函数的定义。
两种实现重抛逻辑的思路
思路1:调整函数设计,让它依赖闭包参数(符合标准库重抛函数的风格)
如果想让你的数组扩展函数成为重抛函数,可以把判断逻辑改成接受一个闭包参数,让闭包负责抛出错误,函数本身只传递这个错误。比如模仿标准库的index(where:):
enum CustomError: Error { case empty case doesNotContainMatch } extension Array where Element == Bool { // 接受一个可能抛出错误的闭包,函数标记为rethrows func indexOfFirst(matching predicate: (Element) throws -> Bool) rethrows -> Int { guard !isEmpty else { // 注意:如果用rethrows,这里不能主动抛出自己的错误! // 要把这类错误的抛出逻辑放到闭包里,或者改用throws fatalError("数组为空,请通过闭包参数处理该场景") } // 这里重抛闭包predicate抛出的错误 guard let detectedIndex = try index(where: predicate) else { // 同样,主动抛出自定义错误会导致rethrows不成立 fatalError("未找到匹配元素,请通过闭包参数处理该场景") } return detectedIndex } }
如果一定要保留自定义错误的抛出,那这个函数必须用throws而不是rethrows——因为主动抛出自己的错误的函数不符合重抛函数的定位。
思路2:让调用这个函数的上层函数成为重抛函数
如果你只是需要在某个上下文里使用重抛逻辑,不需要修改indexOfFirstTrue()本身,可以把调用它的函数声明为rethrows。比如:
// 你的原函数保持不变(还是throws) enum CustomError: Error { case empty case doesNotContainTrue } extension Array where Element == Bool { func indexOfFirstTrue() throws -> Int { if isEmpty { throw CustomError.empty } guard let detectedIndex = index(of: true) else { throw CustomError.doesNotContainTrue } return detectedIndex } } // 上层函数声明为rethrows,它接受一个抛出错误的闭包 func handleArray(_ array: [Bool], with operation: ([Bool]) throws -> Int) rethrows -> Int { return try operation(array) } // 调用示例 let myArray = [false, true, false, true] do { let firstTrueIndex = try handleArray(myArray) { $0.indexOfFirstTrue() } print(firstTrueIndex) // 输出1 } catch CustomError.empty { print("数组是空的") } catch CustomError.doesNotContainTrue { print("数组里没有true") } catch { print("其他错误:\(error)") }
这里handleArray是重抛函数,它本身不抛出错误,只是传递闭包(调用indexOfFirstTrue())抛出的错误。
总结
- 如果你的函数需要主动抛出自己的错误,它必须是
throws函数,不能用rethrows - 只有当函数的错误来源是闭包参数,且函数本身不主动抛错时,才能用
rethrows - 如果你只是需要在某个流程中使用重抛逻辑,可以让调用该函数的上层函数成为重抛函数
内容的提问来源于stack exchange,提问作者Ahmad F
相关产品推荐
相关产品推荐

