mirror of
https://github.com/KaiserY/trpl-zh-cn
synced 2024-11-09 08:51:18 +08:00
commit
9fb200337c
@ -94,11 +94,11 @@
|
|||||||
- [共享状态](ch16-03-shared-state.md)
|
- [共享状态](ch16-03-shared-state.md)
|
||||||
- [可扩展的并发:`Sync`和`Send`](ch16-04-extensible-concurrency-sync-and-send.md)
|
- [可扩展的并发:`Sync`和`Send`](ch16-04-extensible-concurrency-sync-and-send.md)
|
||||||
|
|
||||||
- [面向对象](ch17-00-oop.md)
|
- [面向对象](ch17-00-oop.md)
|
||||||
- [什么是面向对象?](ch17-01-what-is-oo.md)
|
- [什么是面向对象?](ch17-01-what-is-oo.md)
|
||||||
- [为使用不同类型的值而设计的 trait 对象](ch17-02-trait-objects.md)
|
- [为使用不同类型的值而设计的 trait 对象](ch17-02-trait-objects.md)
|
||||||
- [面向对象设计模式的实现](ch17-03-oo-design-patterns.md)
|
- [面向对象设计模式的实现](ch17-03-oo-design-patterns.md)
|
||||||
|
|
||||||
## 高级主题
|
## 高级主题
|
||||||
|
|
||||||
- [模式用来匹配值的结构](ch18-00-patterns.md)
|
- [模式用来匹配值的结构](ch18-00-patterns.md)
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
欢迎阅读 “Rust 程序设计语言”,一本介绍 Rust 的书。Rust 是一门着眼于安全、速度和并发的编程语言。其程序设计兼顾底层语言的性能与控制,并不失高级语言强大的抽象能力。其特性适合那些有类 C 语言经验,正在寻找更安全的替代品的开发者;同样适合有着类 Python 语言背景,寻求在不牺牲表现力的前提下,编写更高性能代码的开发者。
|
欢迎阅读 “Rust 程序设计语言”,一本介绍 Rust 的书。Rust 是一门着眼于安全、速度和并发的编程语言。其程序设计兼顾底层语言的性能与控制,并不失高级语言强大的抽象能力。其特性适合那些有类 C 语言经验,正在寻找更安全的替代品的开发者;同样适合有着类 Python 语言背景,寻求在不牺牲表现力的前提下,编写更高性能代码的开发者。
|
||||||
|
|
||||||
Rust 编译时执行绝大部分的安全检查和内存管理决策,对运行时性能的影响微不足道。这使其在其他语言不擅长的应用场景中得以大显身手:可预测时间和空间需求的程序,嵌入到其他语言中,以及编写如设备驱动和操作系统这样的底层代码,。Rust 也很擅长 web 程序:它驱动着 Rust 包注册网站(package
|
Rust 编译时执行绝大部分的安全检查和内存管理决策,对运行时性能的影响微不足道。这使其在其他语言不擅长的应用场景中得以大显身手:可预测时间和空间需求的程序,嵌入到其他语言中,以及编写如设备驱动和操作系统这样的底层代码,。Rust 也很擅长 web 程序:它驱动着 Rust 包登记网站(package
|
||||||
registry site),[crates.io]!我们由衷期待**你**使用 Rust 进行创作。
|
registry site),[crates.io]!我们由衷期待**你**使用 Rust 进行创作。
|
||||||
|
|
||||||
[crates.io]: https://crates.io/
|
[crates.io]: https://crates.io/
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
## Rust 是一个面向对象的编程语言吗?
|
# Rust 是一个面向对象的编程语言吗?
|
||||||
|
|
||||||
> [ch17-00-oop.md](https://github.com/rust-lang/book/blob/master/second-edition/src/ch17-00-oop.md)
|
> [ch17-00-oop.md](https://github.com/rust-lang/book/blob/master/second-edition/src/ch17-00-oop.md)
|
||||||
> <br>
|
> <br>
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
> <br>
|
> <br>
|
||||||
> commit d06a6a181fd61704cbf7feb55bc61d518c6469f9
|
> commit d06a6a181fd61704cbf7feb55bc61d518c6469f9
|
||||||
|
|
||||||
回顾第十章,我们学习了怎样使用生命周期参数来注解引用来帮助 Rust 理解不同引用的生命周期如何相互联系。见识到了大部分情况 Rust 允许我们省略生命周期,不过每一个引用都有一个生命周期。这里有三个生命周期的高级特征我们还未讲到:**生命周期子类型**(*lifetime subtyping*),**生命周期 bound**(*lifetime bounds*),以及**trait 对象生命周期**(*trait object lifetimes*)。
|
回顾第十章,我们学习了怎样使用生命周期参数来注解引用来帮助 Rust 理解不同引用的生命周期如何相互联系。见识到了大部分情况 Rust 允许我们省略生命周期,不过每一个引用都有一个生命周期。这里有三个生命周期的高级特征我们还未讲到:**生命周期子类型**(*lifetime subtyping*),**生命周期约束**(*lifetime bounds*),以及**trait 对象生命周期**(*trait object lifetimes*)。
|
||||||
|
|
||||||
### 生命周期子类型
|
### 生命周期子类型
|
||||||
|
|
||||||
@ -189,15 +189,15 @@ struct Parser<'c, 's: 'c> {
|
|||||||
|
|
||||||
这是一个非常冗长的例子,不过正如本章的开头所提到的,这类功能是很小众的。你并不会经常需要这个语法,不过当出现类似这样的情形时,却还是有地方可以参考的。
|
这是一个非常冗长的例子,不过正如本章的开头所提到的,这类功能是很小众的。你并不会经常需要这个语法,不过当出现类似这样的情形时,却还是有地方可以参考的。
|
||||||
|
|
||||||
### 生命周期 bound
|
### 生命周期约束(lifetime bound)
|
||||||
|
|
||||||
在第十章,我们讨论了如何在泛型类型上使用 trait bound。也可以像泛型那样为生命周期参数增加限制,这被称为**生命周期 bound**。例如,考虑一下一个封装了引用的类型。回忆一下第十五章的 `RefCell<T>` 类型:其 `borrow` 和 `borrow_mut` 方法分别返回 `Ref` 和 `RefMut` 类型。这些类型是引用的封装,他们在运行时记录检查借用规则。`Ref` 结构体的定义如列表 19-16 所示,现在还不带有生命周期 bound:
|
在第十章,我们讨论了如何在泛型类型上使用 trait bound。也可以像泛型那样为生命周期参数增加限制,这被称为**生命周期约束**。例如,考虑一下一个封装了引用的类型。回忆一下第十五章的 `RefCell<T>` 类型:其 `borrow` 和 `borrow_mut` 方法分别返回 `Ref` 和 `RefMut` 类型。这些类型是引用的封装,他们在运行时记录检查借用规则。`Ref` 结构体的定义如列表 19-16 所示,现在还不带有生命周期约束:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
struct Ref<'a, T>(&'a T);
|
struct Ref<'a, T>(&'a T);
|
||||||
```
|
```
|
||||||
|
|
||||||
<span class="caption">列表 19-16:定义结构体来封装泛型的引用;开始时没有生命周期 bound</span>
|
<span class="caption">列表 19-16:定义结构体来封装泛型的引用;开始时没有生命周期约束</span>
|
||||||
|
|
||||||
若不限制生命周期 `'a` 为与泛型参数 `T` 有关,会得到一个错误因为 Rust 不知道泛型 `T` 会存活多久:
|
若不限制生命周期 `'a` 为与泛型参数 `T` 有关,会得到一个错误因为 Rust 不知道泛型 `T` 会存活多久:
|
||||||
|
|
||||||
@ -218,28 +218,28 @@ note: ...so that the reference type `&'a T` does not outlive the data it points
|
|||||||
|
|
||||||
因为 `T` 可以是任意类型,`T` 自身也可能是一个引用,或者是一个存放了一个或多个引用的类型,而他们各自可能有着不同的生命周期。Rust 不能确认 `T` 会与 `'a` 存活的一样久。
|
因为 `T` 可以是任意类型,`T` 自身也可能是一个引用,或者是一个存放了一个或多个引用的类型,而他们各自可能有着不同的生命周期。Rust 不能确认 `T` 会与 `'a` 存活的一样久。
|
||||||
|
|
||||||
幸运的是,Rust 提供了这个情况下如何指定生命周期 bound 的有用建议:
|
幸运的是,Rust 提供了这个情况下如何指定生命周期约束 的有用建议:
|
||||||
|
|
||||||
```
|
```
|
||||||
consider adding an explicit lifetime bound `T: 'a` so that the reference type
|
consider adding an explicit lifetime bound `T: 'a` so that the reference type
|
||||||
`&'a T` does not outlive the data it points at.
|
`&'a T` does not outlive the data it points at.
|
||||||
```
|
```
|
||||||
|
|
||||||
列表 19-17 展示了按照这个建议,在声明泛型 `T` 时指定生命周期 bound。现在代码可以编译了,因为 `T: 'a` 指定了 `T` 可以为任意类型,不过如果它包含任何引用的话,其生命周期必须至少与 `'a` 一样长:
|
列表 19-17 展示了按照这个建议,在声明泛型 `T` 时指定生命周期约束。现在代码可以编译了,因为 `T: 'a` 指定了 `T` 可以为任意类型,不过如果它包含任何引用的话,其生命周期必须至少与 `'a` 一样长:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
struct Ref<'a, T: 'a>(&'a T);
|
struct Ref<'a, T: 'a>(&'a T);
|
||||||
```
|
```
|
||||||
|
|
||||||
<span class="caption">列表19-17:为 `T` 增加生命周期 bound 来指定 `T` 中的任何引用需至少与 `'a` 存活的一样久</span>
|
<span class="caption">列表19-17:为 `T` 增加生命周期约束 来指定 `T` 中的任何引用需至少与 `'a` 存活的一样久</span>
|
||||||
|
|
||||||
我们可以选择不同的方法来解决这个问题,如列表 19-18 中展示的 `StaticRef` 结构体定义所示,通过在 `T` 上增加 `'static` 生命周期 bound。这意味着如果 `T` 包含任何引用,他们必须有 `'static` 生命周期:
|
我们可以选择不同的方法来解决这个问题,如列表 19-18 中展示的 `StaticRef` 结构体定义所示,通过在 `T` 上增加 `'static` 生命周期约束。这意味着如果 `T` 包含任何引用,他们必须有 `'static` 生命周期:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
struct StaticRef<T: 'static>(&'static T);
|
struct StaticRef<T: 'static>(&'static T);
|
||||||
```
|
```
|
||||||
|
|
||||||
<span class="caption">列表 19-18:在 `T` 上增加 `'static` 生命周期 bound 来限制 `T` 为只拥有 `'static` 引用或没有引用的类型</span>
|
<span class="caption">列表 19-18:在 `T` 上增加 `'static` 生命周期约束 来限制 `T` 为只拥有 `'static` 引用或没有引用的类型</span>
|
||||||
|
|
||||||
没有任何引用的类型被算作 `T: 'static`。因为 `'static` 意味着引用必须同整个程序存活的一样长,一个不包含引用的类型满足所有引用都与程序存活的一样长的标准(因为他们没有引用)。可以这样理解:如果借用检查器关心的是引用是否存活的够久,那么没有引用的类型与有永远存在的引用的类型并没有真正的区别;对于确定引用是否比其所引用的值存活得较短的目的来说两者是一样的。
|
没有任何引用的类型被算作 `T: 'static`。因为 `'static` 意味着引用必须同整个程序存活的一样长,一个不包含引用的类型满足所有引用都与程序存活的一样长的标准(因为他们没有引用)。可以这样理解:如果借用检查器关心的是引用是否存活的够久,那么没有引用的类型与有永远存在的引用的类型并没有真正的区别;对于确定引用是否比其所引用的值存活得较短的目的来说两者是一样的。
|
||||||
|
|
||||||
@ -270,6 +270,6 @@ let obj = Box::new(Bar { x: &num }) as Box<Foo>;
|
|||||||
* 如果只有 `T: 'a`, 则默认是 `'a`。
|
* 如果只有 `T: 'a`, 则默认是 `'a`。
|
||||||
* 如果有多个类似 `T: 'a` 的从句,则没有默认值;必须明确指定。
|
* 如果有多个类似 `T: 'a` 的从句,则没有默认值;必须明确指定。
|
||||||
|
|
||||||
当必须明确指定时,可以为像 `Box<Foo>` 这样的 trait 对象增加生命周期 bound,根据需要使用语法 `Box<Foo + 'a>` 或 `Box<Foo + 'static>`。正如其他的 bound,这意味着任何 `Foo` trait 的实现如果在内部包含有引用, 就必须在 trait 对象 bounds 中为那些引用指定生命周期。
|
当必须明确指定时,可以为像 `Box<Foo>` 这样的 trait 对象增加生命周期约束,根据需要使用语法 `Box<Foo + 'a>` 或 `Box<Foo + 'static>`。正如其他的 bound,这意味着任何 `Foo` trait 的实现如果在内部包含有引用, 就必须在 trait 对象 bounds 中为那些引用指定生命周期。
|
||||||
|
|
||||||
接下来,让我们看看一些其他处理 trait 的功能吧!
|
接下来,让我们看看一些其他处理 trait 的功能吧!
|
||||||
|
Loading…
Reference in New Issue
Block a user