结构体定义
结构体
结构体有点类似于元组,每一部分可以是不同类型。但不同于元组,结构体需要命名各部分数据以便能清楚的表明其值的意义。由于有了这些名字,结构体比元组更灵活:不需要依赖顺序来指定或访问实例中的值。
定义与初始化
定义结构体,需要使用
struct User {
username: String,
email: String,
sign_in_count: u64,
active: bool,
}
一旦定义了结构体后,为了使用它,通过为每个字段指定具体值来创建这个结构体的 实例。创建一个实例需要以结构体的名字开头,接着在大括号中使用
let user1 = User {
email: String::from("someone@example.com"),
username: String::from("someusername123"),
active: true,
sign_in_count: 1,
};
为了从结构体中获取某个特定的值,可以使用点号。如果我们只想要用户的邮箱地址,可以用
let mut user1 = User {
email: String::from("someone@example.com"),
username: String::from("someusername123"),
active: true,
sign_in_count: 1,
};
user1.email = String::from("anotheremail@example.com");
注意整个实例必须是可变的;
简写语法
当参数名与字段名都完全相同时,我们可以使用 字段初始化简写语法(field init shorthand
struct Country {
population: u32,
capital: String,
leader_name: String
}
fn main() {
let population = 500_000;
let capital = String::from("Elist");
let leader_name = String::from("Batu Khasikov");
let kalmykia = Country {
population: population,
capital: capital,
leader_name: leader_name,
};
}
您是否注意到我们写过两次相同的东西?实际上,您不需要这样做。如果字段名和变量名相同,则不必写两次。
struct Country {
population: u32,
capital: String,
leader_name: String
}
fn main() {
let population = 500_000;
let capital = String::from("Elist");
let leader_name = String::from("Batu Khasikov");
let kalmykia = Country {
population,
capital,
leader_name,
};
}
从其他实例更新
使用旧实例的大部分值但改变其部分值来创建一个新的结构体实例通常是很有帮助的。这可以通过 结构体更新语法(struct update syntax)实现。
// 手动更新每个项目
let user2 = User {
email: String::from("another@example.com"),
username: String::from("anotherusername567"),
active: user1.active,
sign_in_count: user1.sign_in_count,
};
// 使用解构更新
let user2 = User {
email: String::from("another@example.com"),
username: String::from("anotherusername567"),
..user1
};
元组结构体
也可以定义与元组类似的结构体,称为 元组结构体(tuple structs
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);
let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);
注意
调试
对于新的{:?}
进行打印,则需要给它提供#[derive(Debug)]
,则可以使用 {:?}
打印它。这些带有 #[]
的消息称为属性。有时,您可以使用它们来告诉编译器使结构具有
#[derive(Debug)]
struct Animal {
age: u8,
animal_type: AnimalType,
}
#[derive(Debug)]
enum AnimalType {
Cat,
Dog,
}
impl Animal {
fn new() -> Self {
// Self means Animal.
//You can also write Animal instead of Self
Self {
// When we write Animal::new(), we always get a cat that is 10 years old
age: 10,
animal_type: AnimalType::Cat,
}
}
fn change_to_dog(&mut self) { // because we are inside Animal, &mut self means &mut Animal
// use .change_to_dog() to change the cat to a dog
// with &mut self we can change it
println!("Changing animal to dog!");
self.animal_type = AnimalType::Dog;
}
fn change_to_cat(&mut self) {
// use .change_to_cat() to change the dog to a cat
// with &mut self we can change it
println!("Changing animal to cat!");
self.animal_type = AnimalType::Cat;
}
fn check_type(&self) {
// we want to read self
match self.animal_type {
AnimalType::Dog => println!("The animal is a dog"),
AnimalType::Cat => println!("The animal is a cat"),
}
}
}
fn main() {
let mut new_animal = Animal::new(); // Associated method to create a new animal
// It is a cat, 10 years old
new_animal.check_type();
new_animal.change_to_dog();
new_animal.check_type();
new_animal.change_to_cat();
new_animal.check_type();
}
The animal is a cat
Changing animal to dog!
The animal is a dog
Changing animal to cat!
The animal is a cat
请记住,Self(fn change_to_dog(&mut self)
即等价于 fn change_to_dog(&mut Animal)
。
enum Mood {
Good,
Bad,
Sleepy,
}
impl Mood {
fn check(&self) {
match self {
Mood::Good => println!("Feeling good!"),
Mood::Bad => println!("Eh, not feeling so good"),
Mood::Sleepy => println!("Need sleep NOW"),
}
}
}
fn main() {
let my_mood = Mood::Sleepy;
my_mood.check();
}