|
|
|
|
@ -1,7 +1,6 @@
|
|
|
|
|
## 结构体的定义和实例化
|
|
|
|
|
|
|
|
|
|
<!-- https://github.com/rust-lang/book/blob/main/src/ch05-01-defining-structs.md -->
|
|
|
|
|
<!-- commit e4681b573677380154825f383546b68e6111a725 -->
|
|
|
|
|
[ch05-01-defining-structs.md](https://github.com/rust-lang/book/blob/8a6130451b0817ead5c2522ce641dcb0f11a8571/src/ch05-01-defining-structs.md)
|
|
|
|
|
|
|
|
|
|
结构体和我们在[“元组类型”][tuples]部分讨论过的元组类似,它们都包含多个相关的值。和元组一样,结构体的每一部分可以是不同类型。但不同于元组,结构体需要命名各部分数据以便能清楚的表明其值的意义。由于有了这些名字,结构体比元组更灵活:不需要依赖顺序来指定或访问实例中的值。
|
|
|
|
|
|
|
|
|
|
@ -47,7 +46,7 @@
|
|
|
|
|
|
|
|
|
|
<span class="caption">示例 5-4:`build_user` 函数获取 email 和用户名并返回 `User` 实例</span>
|
|
|
|
|
|
|
|
|
|
为函数参数起与结构体字段相同的名字是可以理解的,但是不得不重复 `email` 和 `username` 字段名称与变量有些啰嗦。如果结构体有更多字段,重复每个名称就更加烦人了。幸运的是,有一个方便的简写语法!
|
|
|
|
|
为函数参数使用与结构体字段相同的名字是很合理的,但不得不重复写 `email` 和 `username` 这些字段名和变量名,多少有些啰嗦。如果结构体有更多字段,重复每个名称就更烦人了。幸运的是,有一种方便的简写语法!
|
|
|
|
|
|
|
|
|
|
### 使用字段初始化简写语法
|
|
|
|
|
|
|
|
|
|
@ -63,7 +62,7 @@
|
|
|
|
|
|
|
|
|
|
这里我们创建了一个新的 `User` 结构体实例,它有一个叫做 `email` 的字段。我们想要将 `email` 字段的值设置为 `build_user` 函数 `email` 参数的值。因为 `email` 字段与 `email` 参数有着相同的名称,则只需编写 `email` 而不是 `email: email`。
|
|
|
|
|
|
|
|
|
|
### 使用结构体更新语法从其他实例创建实例
|
|
|
|
|
### 使用结构体更新语法创建实例
|
|
|
|
|
|
|
|
|
|
使用旧实例的大部分值但改变其部分值来创建一个新的结构体实例通常是很有用的。这可以通过 **结构体更新语法**(*struct update syntax*)实现。
|
|
|
|
|
|
|
|
|
|
@ -89,9 +88,9 @@
|
|
|
|
|
|
|
|
|
|
示例 5-7 中的代码也在 `user2` 中创建了一个新实例,但该实例中 `email` 字段的值与 `user1` 不同,而 `username`、 `active` 和 `sign_in_count` 字段的值与 `user1` 相同。`..user1` 必须放在最后,以指定其余的字段应从 `user1` 的相应字段中获取其值,但我们可以选择以任何顺序为任意字段指定值,而不用考虑结构体定义中字段的顺序。
|
|
|
|
|
|
|
|
|
|
请注意,结构更新语法就像带有 `=` 的赋值,因为它移动了数据,就像我们在[“使用移动的变量与数据交互”][move]部分讲到的一样。在这个例子中,总体上说我们在创建 `user2` 后就不能再使用 `user1` 了,因为 `user1` 的 `username` 字段中的 `String` 被移到 `user2` 中。如果我们给 `user2` 的 `email` 和 `username` 都赋予新的 `String` 值,从而只复用 `user1` 的 `active` 和 `sign_in_count` 值,那么 `user1` 在创建 `user2` 后仍然有效。`active` 和 `sign_in_count` 的类型是实现 `Copy` trait 的类型,所以我们在[“使用克隆的变量与数据交互”][copy] 部分讨论的行为同样适用。在本例中我们也可以继续使用 `user1.email`,因为它的值并未从 `user1` 中移动出去。
|
|
|
|
|
请注意,结构更新语法就像带有 `=` 的赋值,因为它移动了数据,就像我们在[“使用移动的变量与数据交互”][move]部分讲到的一样。在这个例子中,总体上说我们在创建 `user2` 后就不能再使用 `user1` 了,因为 `user1` 的 `username` 字段中的 `String` 被移到 `user2` 中。如果我们给 `user2` 的 `email` 和 `username` 都赋予新的 `String` 值,从而只复用 `user1` 的 `active` 和 `sign_in_count` 值,那么 `user1` 在创建 `user2` 后仍然有效。`active` 和 `sign_in_count` 的类型是实现 `Copy` trait 的类型,所以我们在[“只在栈上的数据:拷贝”][copy] 部分讨论的行为同样适用。在本例中我们也可以继续使用 `user1.email`,因为它的值并未从 `user1` 中移动出去。
|
|
|
|
|
|
|
|
|
|
### 使用没有命名字段的元组结构体来创建不同的类型
|
|
|
|
|
### 使用元组结构体创建不同的类型
|
|
|
|
|
|
|
|
|
|
也可以定义与元组类似的结构体,称为 **元组结构体**(*tuple structs*)。元组结构体有着结构体名称提供的含义,但没有具体的字段名,只有字段的类型。当你想给整个元组取一个名字,并使元组成为与其他元组不同的类型时,元组结构体是很有用的,这时像常规结构体那样为每个字段命名就显得多余和形式化了。
|
|
|
|
|
|
|
|
|
|
@ -105,9 +104,9 @@
|
|
|
|
|
|
|
|
|
|
注意 `black` 和 `origin` 值的类型不同,因为它们是不同的元组结构体的实例。你定义的每一个结构体有其自己的类型,即使结构体中的字段可能有着相同的类型。例如,一个获取 `Color` 类型参数的函数不能接受 `Point` 作为参数,即便这两个类型都由三个 `i32` 值组成。除此之外,元组结构体实例类似于元组,你可以将它们解构为单独的部分,也可以使用 `.` 后跟索引来访问单独的值。与元组不同的是,解构元组结构体时必须写明结构体的类型。例如,我们可以写 `let Point(x, y, z) = origin;`,将 `origin` 的值解构到名为 `x`、`y` 和 `z` 的变量中。
|
|
|
|
|
|
|
|
|
|
### 没有任何字段的类单元结构体
|
|
|
|
|
### 定义类单元结构体
|
|
|
|
|
|
|
|
|
|
我们也可以定义一个没有任何字段的结构体!它们被称为 **类单元结构体**(*unit-like structs*)因为它们类似于 `()`,即[“元组类型”][tuples]一节中提到的 unit 类型。类单元结构体常常在你想要在某个类型上实现 trait 但不需要在类型中存储数据的时候发挥作用。我们将在第十章介绍 trait。下面是一个声明和实例化一个名为 `AlwaysEqual` 的 unit 结构的示例:
|
|
|
|
|
你也可以定义没有任何字段的结构体!它们被称为 **类单元结构体**(*unit-like structs*),因为它们的行为类似于 `()`,也就是我们在[“元组类型”][tuples]一节中提到的 unit 类型。类单元结构体在你想要在某个类型上实现 trait,但又不需要在该类型本身中存储任何数据时会很有用。我们会在第十章讨论 trait。下面是一个声明和实例化名为 `AlwaysEqual` 的 unit 结构体的例子:
|
|
|
|
|
|
|
|
|
|
<span class="filename">文件名:src/main.rs</span>
|
|
|
|
|
|
|
|
|
|
@ -179,8 +178,8 @@
|
|
|
|
|
> error: could not compile `structs` (bin "structs") due to 2 previous errors
|
|
|
|
|
> ```
|
|
|
|
|
>
|
|
|
|
|
> 第十章会讲到如何修复这个问题以便在结构体中存储引用,不过现在,我们会使用像 `String` 这类拥有所有权的类型来替代 `&str` 这样的引用以修正这个错误。
|
|
|
|
|
> 第十章会讨论如何修复这些错误,从而让你可以在结构体中存储引用;不过现在,我们会用像 `String` 这样的拥有所有权的类型来替代像 `&str` 这样的引用,以此修复这类错误。
|
|
|
|
|
|
|
|
|
|
[tuples]: ch03-02-data-types.html#元组类型
|
|
|
|
|
[move]: ch04-01-what-is-ownership.html#使用移动的变量与数据交互
|
|
|
|
|
[copy]: ch04-01-what-is-ownership.html#使用克隆的变量与数据交互
|
|
|
|
|
[copy]: ch04-01-what-is-ownership.html#只在栈上的数据-拷贝
|
|
|
|
|
|