diff --git a/src/advance/functional-programing/closure.md b/src/advance/functional-programing/closure.md index bc9b14bdf..6775de728 100644 --- a/src/advance/functional-programing/closure.md +++ b/src/advance/functional-programing/closure.md @@ -591,7 +591,7 @@ fn exec<'a, F: Fn(String) -> ()>(f: F) { #### move 和 Fn -在上面,我们讲到了 `move` 关键字对于 `FnOnce` 特征的重要性,但是实际上使用了 `move` 的闭包依然可能实现了 `Fn` 或 `FnMut` 特征。 +在上面,我们讲到了 `move` 关键字对于 `FnOnce` 特征的重要性,但是实际上使用了 `move` 的闭包依然可以使用 `Fn` 或 `FnMut` 特征。 因为,**一个闭包实现了哪种 Fn 特征取决于该闭包如何使用被捕获的变量,而不是取决于闭包如何捕获它们**。`move` 本身强调的就是后者,闭包如何捕获变量: @@ -609,9 +609,9 @@ fn exec(f: F) { } ``` -我们在上面的闭包中使用了 `move` 关键字,所以我们的闭包捕获了它,但是由于闭包对 `s` 的使用仅仅是不可变借用,因此该闭包实际上**还**实现了 `Fn` 特征。 +我们在上面的闭包中使用了 `move` 关键字,所以我们的闭包捕获了它,但是由于闭包获取了 `s` 的所有权,因此该闭包实现了 `FnOnce` 的特征。 -细心的读者肯定发现我在上段中使用了一个 `还` 字,这是什么意思呢?因为该闭包不仅仅实现了 `FnOnce` 特征,还实现了 `Fn` 特征,将代码修改成下面这样,依然可以编译: +但是假如我们将代码修改成下面这样,依然可以编译: ```rust fn main() { @@ -627,6 +627,8 @@ fn exec(f: F) { } ``` +奇怪, 明明是闭包实现的是 `FnOnce` 的特征, 为什么编译器居然允许 `Fn` 特征通过编译呢? + #### 三种 Fn 的关系 实际上,一个闭包并不仅仅实现某一种 `Fn` 特征,规则如下: