定义并实例化结构体
结构体(struct,或者 structure),是一种自定义数据类型,允许你命名和包装多个相关的值,这些值在定义时称之为字段(field)可以被视为数据对象的属性。同样是将不同类型的数据包装组织起来,结构体相比于元组更加灵活,不依赖其中属性的顺序。
除了基本的定义与使用,需要注意以下几点:
- 可变结构体类型:当结构体数据类型的变量为可变时,其中所有属性都可变。
- 结构体初始化语法简化:可以通过同名变量赋值来简写初始化语法。
- 结构体更新语法:基于其它已定义的结构体变量来初始化时,可以使用
..
语法指定了剩余未显式设置值的字段。 - 元组结构体:没有显式的字段名,与元组相区别就是其代表了特定的类型。
- 类单元结构体(unit-like structs):类似于
()
,即 unit 类型,解释一下,当需要对某个类型实现trait
时,由于此时并不在意类型本身的属性,此时只定义结构体类型,而不设置其字段。 - 结构体数据的所有权:当结构体的某一属性需要存储其它数据的引用时,据上一部分中介绍的所有权知识,结构体变量本身只是拥有该属性数据的使用权,所以为了确保结构体数据的有效性,就要确保该引用指向的数据的有效。为了使结构体可以存储引用,就需要在定义结构体与引用相关的字段时指定该引用的生命周期(lifetimes),这在之后的内容有专门介绍。
一个使用结构体的示例程序
从不使用任何数据组织方式,到使用元组,最后到使用结构体完成计算面积这一示例,体现了结构体的优势。其中,需要了解的额外内容有:
- 结构体的
Display trait
和Debug trait
,及对应的println!()
宏的占位符{}
和{:?}
或{:#?}
- 对于
#[derive(Debug)]
注解的使用,通过注解的形式可以直接为结构体添加一些常用的trait
。 - 对于与结构体相关联的方法可以直接在结构体中实现。
方法语法
可以在 impl
结构体名的代码块中实现结构体的方法,之后可通过方法语法(method syntax)在实例上调用实现的方法,使用运算符 .
来调用。
结构体方法定义和实现与普通函数几乎一致,但是其默认会传入 self
参数代表结构体类型的实例,传入分为四种情况,注意区分:
&self
&mut self
self
:比较少用,适用于在方法语法中将原实例转为新的实例的情况。- 不传入 self:此时称这个“方法”为关联函数(associated functions),即此方法的调用不依赖实例,它是一个函数,并不是方法(所以前面用引号)。关联函数经常被用作返回一个结构体新实例的构造函数,如
String::from()
。
而且,每个结构体都允许拥有多个 impl
块,其实现的效果与一个块一致。
另外,由于 Rust 具有称为 自动引用和解引用(automatic referencing and dereferencing)的功能。当使用 object.something()
调用方法时,Rust 会自动为 object
添加 &
、&mut
或 *
以便使 object
与方法签名匹配。