|
|
|
@ -2,7 +2,7 @@
|
|
|
|
|
|
|
|
|
|
> [ch05-02-example-structs.md](https://github.com/rust-lang/book/blob/main/src/ch05-02-example-structs.md)
|
|
|
|
|
> <br>
|
|
|
|
|
> commit fab5832e5f64bd2a783c4687048b266194a72792
|
|
|
|
|
> commit 15aef431579a3d2f2bac8cc25445ece1c8e9808c
|
|
|
|
|
|
|
|
|
|
为了理解何时会需要使用结构体,让我们编写一个计算长方形面积的程序。我们会从单独的变量开始,接着重构程序直到使用结构体替代他们为止。
|
|
|
|
|
|
|
|
|
@ -38,7 +38,7 @@ $ cargo run
|
|
|
|
|
The area of the rectangle is 1500 square pixels.
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
虽然示例 5-8 可以运行,并在调用 `area` 函数时传入每个维度来计算出长方形的面积,不过我们可以做的更好。宽度和高度是相关联的,因为他们在一起才能定义一个长方形。
|
|
|
|
|
这个示例代码在调用 `area` 函数时传入每个维度,虽然可以正确计算出长方形的面积,但我们仍然可以修改这段代码来使它的意义更加明确,并且增加可读性。
|
|
|
|
|
|
|
|
|
|
这些代码的问题突显在 `area` 的签名上:
|
|
|
|
|
|
|
|
|
@ -77,7 +77,7 @@ fn area(dimensions: (u32, u32)) -> u32 {
|
|
|
|
|
|
|
|
|
|
### 使用结构体重构:赋予更多意义
|
|
|
|
|
|
|
|
|
|
我们使用结构体为数据命名来为其赋予意义。我们可以将我们正在使用的元组转换成一个有整体名称而且每个部分也有对应名字的数据类型,如示例 5-10 所示:
|
|
|
|
|
我们使用结构体为数据命名来为其赋予意义。我们可以将我们正在使用的元组转换成一个有整体名称而且每个部分也有对应名字的结构体,如示例 5-10 所示:
|
|
|
|
|
|
|
|
|
|
<span class="filename">文件名: src/main.rs</span>
|
|
|
|
|
|
|
|
|
@ -111,7 +111,7 @@ fn area(rectangle: &Rectangle) -> u32 {
|
|
|
|
|
|
|
|
|
|
### 通过派生 trait 增加实用功能
|
|
|
|
|
|
|
|
|
|
如果能够在调试程序时打印出 `Rectangle` 实例来查看其所有字段的值就更好了。示例 5-11 像前面章节那样尝试使用 [`println!` 宏][println]。但这并不行。
|
|
|
|
|
在调试程序时打印出 `Rectangle` 实例来查看其所有字段的值非常有用。示例 5-11 像前面章节那样尝试使用 [`println!` 宏][println]。但这并不行。
|
|
|
|
|
|
|
|
|
|
<span class="filename">文件名: src/main.rs</span>
|
|
|
|
|
|
|
|
|
@ -136,7 +136,7 @@ fn main() {
|
|
|
|
|
error[E0277]: `Rectangle` doesn't implement `std::fmt::Display`
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
`println!` 宏能处理很多类型的格式,不过,`{}` 默认告诉 `println!` 使用被称为 `Display` 的格式:意在提供给直接终端用户查看的输出。目前为止见过的基本类型都默认实现了 `Display`,因为它就是向用户展示 `1` 或其他任何基本类型的唯一方式。不过对于结构体,`println!` 应该用来输出的格式是不明确的,因为这有更多显示的可能性:是否需要逗号?需要打印出大括号吗?所有字段都应该显示吗?由于这种不确定性,Rust 不会尝试猜测我们的意图,所以结构体并没有提供一个 `Display` 实现。
|
|
|
|
|
`println!` 宏能处理很多类型的格式,不过,`{}` 默认告诉 `println!` 使用被称为 `Display` 的格式:意在提供给直接终端用户查看的输出。目前为止见过的基本类型都默认实现了 `Display`,因为它就是向用户展示 `1` 或其他任何基本类型的唯一方式。不过对于结构体,`println!` 应该用来输出的格式是不明确的,因为这有更多显示的可能性:是否需要逗号?需要打印出大括号吗?所有字段都应该显示吗?由于这种不确定性,Rust 不会尝试猜测我们的意图,所以结构体并没有提供一个 `Display` 实现来使用 `println!` 与 `{}` 占位符。
|
|
|
|
|
|
|
|
|
|
但是如果我们继续阅读错误,将会发现这个有帮助的信息:
|
|
|
|
|
|
|
|
|
@ -190,7 +190,7 @@ $ cargo run
|
|
|
|
|
rect1 is Rectangle { width: 30, height: 50 }
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
好极了!这并不是最漂亮的输出,不过它显示这个实例的所有字段,毫无疑问这对调试有帮助。当我们有一个更大的结构体时,能有更易读一点的输出就好了,为此可以使用 `{:#?}` 替换 `println!` 字符串中的 `{:?}`。如果在这个例子中使用了 `{:#?}` 风格的话,输出会看起来像这样:
|
|
|
|
|
好极了!这并不是最漂亮的输出,不过它显示这个实例的所有字段,毫无疑问这对调试有帮助。当我们有一个更大的结构体时,能有更易读一点的输出就好了,为此可以使用 `{:#?}` 替换 `println!` 字符串中的 `{:?}`。在这个例子中使用 `{:#?}` 风格将会输出:
|
|
|
|
|
|
|
|
|
|
```console
|
|
|
|
|
$ cargo run
|
|
|
|
@ -203,7 +203,11 @@ rect1 is Rectangle {
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
另一种使用 `Debug` 格式打印数值的方法是使用 [`dbg!` 宏][dbg]。`dbg!` 宏接收一个表达式的所有权,打印出代码中调用 dbg! 宏时所在的文件和行号,以及该表达式的结果值,并返回该值的所有权。调用 `dbg!` 宏会打印到标准错误控制台流(`stderr`),而不是 `println!`,后者会打印到标准输出控制台流(`stdout`)。我们将在[第十二章 “将错误信息写入标准错误而不是标准输出” 一节][err]中更多地讨论 `stderr` 和 `stdout`。下面是一个例子,我们对分配给 `width` 字段的值以及 `rect1` 中整个结构的值感兴趣。
|
|
|
|
|
另一种使用 `Debug` 格式打印数值的方法是使用 [`dbg!` 宏][dbg]。`dbg!` 宏接收一个表达式的所有权,打印出代码中调用 dbg! 宏时所在的文件和行号,以及该表达式的结果值,并返回该值的所有权。
|
|
|
|
|
|
|
|
|
|
> 注意:调用 `dbg!` 宏会打印到标准错误控制台流(`stderr`),与 `println!` 不同,后者会打印到标准输出控制台流(`stdout`)。我们将在[第十二章 “将错误信息写入标准错误而不是标准输出” 一节][err]中更多地讨论 `stderr` 和 `stdout`。
|
|
|
|
|
|
|
|
|
|
下面是一个例子,我们对分配给 `width` 字段的值以及 `rect1` 中整个结构的值感兴趣。
|
|
|
|
|
|
|
|
|
|
```rust
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
@ -222,7 +226,7 @@ fn main() {
|
|
|
|
|
dbg!(&rect1);
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
我们可以把 `dbg!` 放在表达式 `30 * scale` 周围,因为 `dbg!` 返回表达式的值的所有权,所以 `width` 字段将获得相同的值,就像我们在那里没有 `dbg!` 调用一样。我们不希望 `dbg!` 拥有 `rect1` 的所有权,所以我们在下一次调用 dbg! 时传递一个引用。下面是这个例子的输出结果:
|
|
|
|
|
我们可以把 `dbg!` 放在表达式 `30 * scale` 周围,因为 `dbg!` 返回表达式的值的所有权,所以 `width` 字段将获得相同的值,就像我们在那里没有 `dbg!` 调用一样。我们不希望 `dbg!` 拥有 `rect1` 的所有权,所以我们在下一次调用 `dbg!` 时传递一个引用。下面是这个例子的输出结果:
|
|
|
|
|
|
|
|
|
|
```console
|
|
|
|
|
$ cargo run
|
|
|
|
|