Swift 中的 throws 和 rethrows 有啥区别?
Posted
技术标签:
【中文标题】Swift 中的 throws 和 rethrows 有啥区别?【英文标题】:What are the differences between throws and rethrows in Swift?Swift 中的 throws 和 rethrows 有什么区别? 【发布时间】:2017-09-04 10:16:08 【问题描述】:在搜索了一些参考资料以弄清楚之后,-不幸的是-我找不到有用且简单的描述来了解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
时,我们应该遵循什么逻辑?
【问题讨论】:
【参考方案1】:来自 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
被调用时带有一个 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
被声明为 throws
而不是 rethrows
那么你会
即使在示例 1 中,也必须使用 try
调用它,
这是“不方便的”并且使代码变得不必要。
如果在没有throws/rethrows
的情况下声明了map
,那么你不能
如示例 2 所示,使用抛出的闭包调用它。
Swift 标准库中的其他方法也是如此
采用函数参数:filter()
、index(where:)
、forEach()
等等。
在你的情况下,
func throwCustomError(function:(String) throws -> ()) throws
表示一个可以抛出错误的函数,即使调用 一个非抛出的参数,而
func rethrowCustomError(function:(String) throws -> ()) rethrows
表示仅在使用 a 调用时抛出错误的函数 抛出论据。
粗略地说,rethrows
用于不抛出异常的函数
“自行”错误,但仅从其功能“转发”错误
参数。
【讨论】:
最后一句话是金! @Honey:答案的最后一句话是我的总结。 是的,这似乎更好。说rethrow
s 仅与闭包一起使用是否正确,而不是不需要它们?
@Honey:我不完全明白你的意思。 rethrows
仅与接受可能抛出的函数参数的函数一起使用。
如果两者都做,语法会怎样? ?? 会不会是“再扔”??【参考方案2】:
只是在马丁的回答中添加一些内容。与抛出函数具有相同签名的非抛出函数被视为抛出函数的sub-type
。这就是为什么 rethrows 可以确定它是哪一个,并且仅在 func 参数也抛出时才需要 try
,但仍然接受不抛出的相同函数签名。这是一种方便的方法,只需要在 func 参数抛出时使用 do try 块,但函数中的其他代码不会抛出错误。
【讨论】:
以上是关于Swift 中的 throws 和 rethrows 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章
《从零开始学Swift》学习笔记(Day3)——Swift2.0之后增加的关键字
nodejs连接mysql报错throw err; // Rethrow non-MySQL errors解决方法
nodejs连接mysql报错:throw err; // Rethrow non-MySQL errors TypeError: Cannot read property 'query&