在搜索了一些参考资料后,很明显 - 我找不到有用的和简单的描述来理解throws
和rethrows
之间的差异。当试图理解我们应该如何使用它时,这有点令人困惑。
我想提一下,我很熟悉-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
必须由try
处理的函数,与rethrows
不同。所以呢?!在决定使用throws
或rethrows
?
答案 0 :(得分:133)
来自Swift书中的"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
,那么它本身就可以抛出
并且必须使用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
调用它,
这是&#34;不方便&#34;并且不需要代码。 map
没有throws/rethrows
,那么你就不能
如示例2所示,使用抛出闭包来调用它。 Swift标准库中的其他方法也是如此
它采用函数参数:filter()
,index(where:)
,forEach()
等等。
在你的情况下,
func throwCustomError(function:(String) throws -> ()) throws
表示即使调用了也可以抛出错误的函数 一个非投掷的论点,而
func rethrowCustomError(function:(String) throws -> ()) rethrows
表示仅在使用a调用时才会抛出错误的函数 抛出争论。
粗略地说,rethrows
用于不抛出的函数
错误&#34;他们自己&#34;,但只有&#34;转发&#34;他们的功能错误
参数。
答案 1 :(得分:12)
只是添加一些东西以及马丁的回答。具有与投掷函数相同的签名的非投掷函数被认为是投掷函数的sub-type
。这就是为什么rethrows可以确定它是哪一个,并且当func param也抛出时只需要try
,但仍然接受不抛出的相同函数签名。这是一个方便的方法,只需要在func param抛出时使用do try块,但函数中的其他代码不会抛出错误。