理解Swift中的关键字throw和rethrows

Swift中throwrethrows关键字用于异常处理(Error handling),都是用在函数中,可以简单理解为throw让函数或者方法可能出现的异常得到处理(比如用do-catch处理),而rethrows只是传递throw,本身没有针对函数或方法,下面详细解释一下:

throw

throws关键字首先用在函数申明中,放在返回类型的前面,比如标准库中map的函数签名:

func map(_ 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时抛出异常

你可能感兴趣的:(理解Swift中的关键字throw和rethrows)