2017-04-09 55 views
21

在搜索了一些参考文献以找出它之后,我很难找到有用的简单描述来了解throwsrethrows之间的区别。试图了解我们应该如何使用它时,这有点令人困惑。Swift中的抛出和反馈有什么区别?

我会告诉你我有种熟悉的 - 默认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它必须由try处理,不像rethrows函数时。所以呢?!当决定使用throwsrethrows时,我们应遵循什么逻辑?

回答

57

"Declarations"在斯威夫特书:

重新抛出函数和方法

一个函数或方法可以与rethrows关键字 声明表明,它抛出一个错误只有一个它的功能 参数会引发错误。这些功能和方法被称为 重新抛光功能重新抛光方法。回滚函数和 方法必须至少有一个抛出函数参数。

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

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

如果map被称为具有非抛变换,它不会引发 错误本身,并且可以被称为无try

// Example 1: 

let a = [1, 2, 3] 

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

let a1 = a.map(f1) 

但是,如果map被调用了投掷闭包,那么它本身可以抛出 d必须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被宣布为throws代替rethrows那么你就 甚至已经在例1 try称呼它, 这是“不方便”和腌代码不必要。
  • 如果map被声明没有throws/rethrows那么你不能用 用例2中的抛出闭包来调用它。

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

在你的情况,

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

表示功能,可以抛出一个错误,即使调用 非投掷的说法,而

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

表示这将引发错误的函数只有在调用 的投掷参数时才有效。

粗略地讲,rethrows是不“靠自己”扔 错误的功能,但只有“前进”的错误,从它们的功能 参数。

+1

很好的回答。谢谢。 – Darko

+3

最后一句话是金色的! – Klaas

+1

所以我想总结一下,当你*可能会抛出时'重新抛出'。当你想**限制为总是投掷时投掷''' – Honey

7

只是添加了一些与马丁的答案。具有与投掷功能相同签名的非投掷功能被认为是投掷功能的sub-type。这就是为什么rethrows可以决定它是哪一个,并且只有当func param也抛出时才需要try,但仍然接受不抛出的相同函数签名。当func参数抛出时,只需要使用do try块就是一种方便的方法,但函数中的其他代码不会引发错误。

相关问题