把一组数据聚在一起,并把每个组当作一个整体来处理,往往很有用。在 Rust 里,这样的组叫作结构体,组里的每一项都是结构体的一个字段。结构体定义了它有哪些字段,而结构体的一个具体例子叫作实例。
此外,结构体上还可以定义方法,这些方法可以访问结构体的字段。在这种情况下,结构体本身就被称为self。当方法使用&mut self时,字段可以被改变,也就是被修改。当方法使用&self时,字段不能被改变:它们是不可变的。控制可变性有助于借用检查器保证 Rust 中整类并发 bug 根本不会出现。
在这个练习里,你会为一个结构体实现两种方法。第一种通常叫作 getter:它们把结构体的字段暴露给外界,同时不让任何其他人修改这个值。在 Rust 里,这类方法按照惯例会与它们所暴露的字段同名,也就是说,如果有一个 getter 方法取的是名为name的字段,这个方法就简单地叫作name()。
你还会实现另一类方法,通常叫作 setter。它们会改变字段的值。setter 在 Rust 里并不常见。如果一个字段可以被自由修改,更常见的做法是直接把它设为公开。但如果更新字段会带来副作用,或者需要进行访问控制,setter 就很有用:一个标记为pub(crate)的 setter 允许同一个 crate 中的其他模块更新私有字段,而外界无法影响这个字段。
结构体有三种:带命名字段的结构体、元组结构体和单元结构体。在这个概念练习中,我们会探索第一种:带命名字段的结构体。
结构体使用struct关键字来定义,后面跟所描述类型的大写名称:
struct Item {}
然后,把其他类型作为结构体的_字段_引入结构体主体,每个字段都有自己的类型:
struct Item {
name: String,
weight: f32,
worth: u32,
}
最后,可以在impl块中为结构体定义方法:
impl Item {
// initializes and returns a new instance of our Item struct
fn new() -> Self {
todo!()
}
}
对结构体语法的简要介绍就到这里,接下来请看看这个练习的说明!
你正在实现一个健康监测系统。为此,你需要记录用户的健康统计数据。
一开始,impl块中会有一些存根函数,以及下面这个结构体定义:
pub struct User {
name: String,
age: u32,
weight: f32,
}
你的目标是实现impl块中定义的User struct上的这些存根方法。
例如,new方法应该返回一个User结构体实例,其中包含指定的姓名、年龄和体重值。
let mut bob = User::new(String::from("Bob"), 32, 155.2);
// Returns: a User with name "Bob", age 32, and weight 155.2
weight方法应该返回User的体重。
bob.weight();
// Returns: 155.2
set_age方法应该设置User的年龄。
bob.set_age(33);
// Updates Bob's age to 33; happy birthday Bob!
祝你玩得开心!