结构体和我们在“元组类型”部分论过的元组类似,它们都包含多个相关的值。和元组一样,结构体的每一部分可以是不同类型。但不同于元组,结构体需要命名各部分数据以便能清楚的表明其值的意义。由于有了这些名字,结构体比元组更灵活:不需要依赖顺序来指定或访问实例中的值。
struct User {
active: bool,
username: String,
email: String,
sign_in_count: u64,
}
结构体赋值
fn build_user(email: String, username: String) -> User {
User {
active: true,
username: username,
email: email,
sign_in_count: 1,
}
}
简化赋值
Rust在给结构体赋值时可以简化,行为与JavaScript类似
fn build_user(email: String, username: String) -> User {
User {
active: true,
username,
email,
sign_in_count: 1,
}
}
当参数与结构体的字段同名时,可以简化写法
从其他实例创建实例
fn main() {
// --snip--
let user2 = User {
email: String::from("[email protected]"),
..user1
};
}
当需要从一个实例创建另一个实例时,除了常规的每个字段都进行赋值,还可以选择这种结构体更新语法,近指定需要变化的字段,然后解构原来的结构体(与JavaScript中的解构赋值类似)
特殊的结构体
元组结构体
元组结构体有着结构体名称提供的含义,但没有具体的字段名,只有字段的类型。
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);
如果是元组,那么同样的三个整数是没有区分的,但是元组结构体能够表明这里是RGB颜色,还是XYZ坐标
类单元结构体
一个没有任何字段的结构体,它们被称为 类单元结构体(unit-like structs)因为它们类似于 ()
类单元结构体常常在你想要在某个类型上实现 trait 但不需要在类型中存储数据的时候发挥作用。
结构体方法
方法与函数类似,它们使用 fn 关键字和名称声明,可以拥有参数和返回值,同时包含在某处调用该方法时会执行的代码。不过方法与函数是不同的,因为它们在结构体的上下文中被定义(或者是枚举或 trait 对象的上下文),并且它们第一个参数总是 self,它代表调用该方法的结构体实例。
struct Rectangle {
width: u32,
height: u32,
}
// impl 是 implementation 的缩写
// 这个 impl 块中的所有内容都将与 Rectangle 类型相关联
impl Rectangle {
fn area(&self) -> u32 {
self.width * self.height
}
}
方法语法获取一个实例并加上一个点号,后跟方法名、圆括号以及任何参数。
fn main() {
let rect1 = Rectangle {
width: 30,
height: 50,
};
println!(
"The area of the rectangle is {} square pixels.",
// 方法语法获取一个实例并加上一个点号,后跟方法名、圆括号以及任何参数。
rect1.area()
);
}
关联函数
所有在 impl 块中定义的函数被称为 关联函数(associated functions),因为它们与 impl 后面命名的类型相关。我们可以定义不以 self 为第一参数的关联函数(因此不是方法),因为它们并不作用于一个结构体的实例。我们已经使用了一个这样的函数:在 String 类型上定义的 String::from 函数。
struct Rectangle {
width: u32,
height: u32,
}
impl Rectangle {
fn square(size: u32) -> Self {
Self {
width: size,
height: size,
}
}
}
// 调用关联函数,使用结构体名和 :: 语法
let sq = Rectangle::square(3)
不是方法的关联函数经常被用作返回一个结构体新实例的构造函数。这些函数的名称通常为 new ,但 new 并不是一个关键字