Swift中的掷球和掷球有什么区别?


81

经过寻找一些参考的数字出来,-unfortunately-我找不到任何关于理解之间的差异有用-和简单-描述throwsrethrows。当试图了解我们应该如何使用它们时,这有点令人困惑。

我要说的是,我对-default-最为熟悉,它throws具有传播错误的最简单形式,如下所示:

enum CustomError: Error {
    case potato
    case tomato
}

func throwCustomError(_ string: String) throws {
    if string.lowercased().trimmingCharacters(in: .whitespaces) == "potato" {
        throw CustomError.potato
    }

    if string.lowercased().trimmingCharacters(in: .whitespaces) == "tomato" {
        throw CustomError.tomato
    }
}

do {
    try throwCustomError("potato")
} catch let error as CustomError {
    switch error {
    case .potato:
        print("potatos catched") // potatos catched
    case .tomato:
        print("tomato catched")
    }
}

到目前为止还不错,但是在以下情况下会出现问题:

func throwCustomError(function:(String) throws -> ()) throws {
    try function("throws string")
}

func rethrowCustomError(function:(String) throws -> ()) rethrows {
    try function("rethrows string")
}

rethrowCustomError { string in
    print(string) // rethrows string
}

try throwCustomError { string in
    print(string) // throws string
}

到目前为止我所知道的是当调用一个函数时throws必须由a处理try,而与rethrows。所以呢?!在决定使用throws或时应遵循的逻辑是什么rethrows

Answers:


184

“声明”在斯威夫特书:

重投功能和方法

可以使用rethrows关键字声明函数或方法,以表明仅当函数的一个函数参数抛出错误时,该函数或方法才会抛出错误。这些功能和方法称为 重新抛出函数重新抛出方法。抛出函数和方法必须至少具有一个抛出函数参数。

一个典型的例子是map方法:

public func map<T>(_ transform: (Element) throws -> T) rethrows -> [T]

如果map使用非抛出转换调用if ,则它本身不会抛出错误,并且可以在没有以下情况的情况下调用try

// Example 1:

let a = [1, 2, 3]

func f1(n: Int) -> Int {
    return n * n
}

let a1 = a.map(f1)

但是,如果map使用throwing闭包调用,则本身可以抛出,必须使用调用try

// Example 2:

let a = [1, 2, 3]
enum CustomError: Error {
    case illegalArgument
}

func f2(n: Int) throws -> Int {
    guard n >= 0 else {
        throw CustomError.illegalArgument
    }
    return n*n
}


do {
    let a2 = try a.map(f2)
} catch {
    // ...
}
  • 如果map声明为throwsrethrowstry即使在示例1中也必须调用它,这“很不方便”,并且使代码不必要。
  • 如果map没有声明,throws/rethrows则无法像示例2那样使用抛出闭包来调用它。

同样是从雨燕标准库的其它方法取功能参数真:filter()index(where:)forEach()和许多许多。

就你而言

func throwCustomError(function:(String) throws -> ()) throws

表示即使使用非抛出参数调用也可能抛出错误的函数,而

func rethrowCustomError(function:(String) throws -> ()) rethrows

表示仅当使用throwing参数调用时才会引发错误的函数。

粗略地说,rethrows是针对不会“独自”抛出错误,而仅从其函数参数中“转发”错误的函数。


36
最后一句话是金!
克拉斯

1
@Honey:答案的最后一句话是我的总结。
Martin R

是的,看起来更好。说rethrows仅与闭包一起使用,而不是不需要闭包,这是正确的吗?
亲爱的

3
@Honey:我没有完全理解你的意思。rethrows仅与带有可能抛出的函数参数的函数一起使用。
Martin R

如果两者都做,语法将如何?“会是“掷球”吗?
Kautsya Kanu

14

只是为了增加一些与马丁的答案。具有与投掷函数相同签名的非投掷函数被视为投掷函数中的一个sub-type。这就是为什么重新抛出可以确定它是哪一个,并且仅try在func参数也抛出时才需要,而仍然接受不抛出的相同函数签名。这是一种方便的方法,仅在func参数抛出时必须使用do try块,但是函数中的其他代码不会抛出错误。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.