Swift中throw
和rethrows
关键字用于异常处理(Error handling),都是用在函数中,可以简单理解为throw让函数或者方法可能出现的异常得到处理(比如用do-catch处理),而rethrows
只是传递throw
,本身没有针对函数或方法,下面详细解释一下:
throw
throws
关键字首先用在函数申明中,放在返回类型的前面,比如标准库中map的函数签名:
func map<T>(_ transform: (Int) throws -> T) rethrows -> [T]
然后在函数内部,如果出现可能的异常,就可以throw这个异常,通常可以用一个枚举来代表一类异常,这个枚举可以实现Error
协议,比如:
enum TestError: Error {
case errorOne(Int)
case errorTwo(String)
case errorThree
case errorUnknown
}
func testThrow(num: Int) throws -> String {
switch num {
case 1:
throw TestError.errorOne(1)
case 2:
throw TestError.errorTwo("2")
case 3:
throw TestError.errorThree
case 4:
throw TestError.errorUnknown
default:
return "No Error"
}
}
这样,通过throw函数中可能出现的异常,让函数反馈错误,强制调用这个函数的程序员处理所有可能的错误,减少维护成本。
下面使用do-catch来处理可能的异常:
do {
let testResult: String = try testThrow(num: 2)
print(testResult) // Will no print
} catch TestError.errorOne(let num) {
print(num) // 1
} catch TestError.errorTwo(let str) {
print(str) // 2
} catch TestError.errorThree {
print(TestError.errorThree) // errorThree
} catch let err {
print(err) // errorUnknown
}
// 2
rethrows
rethrows
关键字只起到传递异常的作用,在一个函数或者方法中,调用一个会throw的函数,就可以通过rethrows传递可能的异常,接上面的例子:
func testRethrow(testThrowCall: (Int) throws -> String, num: Int) rethrows -> String {
try testThrowCall(num)
}
观察函数申明,其实就是有一个会throw函数作为参数,然后在返回类型前面添加关键字rethrows
,函数内部直接调用那个会throw的函数,传递可能的异常,处理rethrows的函数或方法就和处理throw的函数或方法一样:
do {
let testResult: String = try testRethrow(testThrowCall: testThrow, num: 4)
print(testResult) // Will no print
} catch TestError.errorOne(let num) {
print(num) // 1
} catch TestError.errorTwo(let str) {
print(str) // 2
} catch TestError.errorThree {
print(TestError.errorThree) // errorThree
} catch let err {
print(err) // errorUnknown
}
// errorUnknown
总结
throw在函数或者方法中抛出异常,让调用者必须明确地处理可能的异常,rethrows本身并不抛出异常或者处理异常,其只起到传递异常的作用,最后回到标准库中的map函数,综合上述举个例子:
enum NegativeError: Error {
case negative
}
let nums = [-1, 1, 2, 3, 4]
do {
let strNums = try nums.map { (num) throws -> String in
if num >= 0 {
return String(num)
} else {
throw NegativeError.negative
}
}
print(strNums) // Will no print
} catch let err {
print(err)
}
// negative
这里在map的函数参数中使用了throw,当元素小于0时抛出异常