一个 struct 就是一些字段的集合。
字段是一个与数据类型相关联的数据值。它的值可以是基本类型或者是结构体类型。
它的定义就像是给编译器的蓝图,告诉编译器如何在内容中布局彼此相邻的字段。
struct SeaCreature {
// String 是个结构体
animal_type: String,
name: String,
arms: i32,
legs: i32,
weapon: String,
}
与函数(function)不同,方法(method)是与特定数据类型关联的函数。
静态方法-属于某个类型,调用时使用 :: 运算符
动态方法-属于某个类型的实例,调用时使用 . 运算符
fn main() {
// 使用静态方法来创建一个String实例
let s = String::from("Hello world!");
// 使用实例来调用动态方法
println!("{} is {} characters long.", s, s.len());
}
Rust 程序有3个存放数据的内存区域:
当我们在代码中实例化一个结构体时,我们的程序会在内存中并排创建相关的字段数据。
当我们通过制定所有字段值的方式来实例化时:
结构体 { … };
结构体字段可以通过 . 运算符来获取。
struct SeaCreature {
animal_type: String,
name: String,
arms: i32,
legs: i32,
weapon: String,
}
fn main() {
// SeaCreature 的数据在栈上
let ferris = SeaCreature {
// String 结构体也在栈上
// 但也存放了一个数据在栈上
animal_type: String::from("螃蟹"),
name: String::from("Ferris"),
arms: 2,
legs: 4,
weapon: String::from("大钳子"),
};
let sarah = SeaCreature {
animal_type: String::from("章鱼"),
name: String::from("Sarah"),
arms: 8,
legs: 0,
weapon: String::from("无"),
};
println!(
"{} 是只 {}。 它有 {} 只胳膊 {} 只腿。还有一个{}。",
ferris.name, ferris.animal_type, ferris.arms, ferris.legs, ferris.weapon
);
println!(
"{} 是只 {}。 它有 {} 只胳膊 {} 只腿。它没有杀伤性武器~",
sarah.name, sarah.animal_type, sarah.arms, sarah.legs
);
}
这个例子中的内存详情:
简洁起见,可以创建像元组一样被使用的结构体。
struct Location(i32, i32);
fn main() {
// 这仍然是一个在栈上的结构体
let loc = Location(42, 32);
println!("{}, {}", loc.0, loc.1);
}
结构体也可以没有任何字段。
就像第一章中提到的, 一个unit是一个空元组()的别称。这就是为什么,此类结构体被称为类单元。
这种类型的结构体很少用到。
struct Marker;
fn main() {
let _m = Marker;
}
枚举允许使用 enum 关键字创建一个新类型,该类型的值可以包括几个带标记的元素。
match 有助于确保对多有可能的枚举值进行彻底的处理,使其成为确保高质量代码的强大工具。
#![allow(dead_code)] // this line prevents compiler warnings
enum Species {
Crab,
Octopus,
Fish,
Clam
}
struct SeaCreature {
species: Species,
name: String,
arms: i32,
legs: i32,
weapon: String,
}
fn main() {
let ferris = SeaCreature {
species: Species::Crab,
name: String::from("Ferris"),
arms: 2,
legs: 4,
weapon: String::from("claw"),
};
match ferris.species {
Species::Crab => println!("{} is a crab.", ferris.name),
Species::Octopus => println!("{} is a Octopus", ferris.name),
Species::Fish => println!("{} is a fish", ferris.name),
Species::Clam => println!("{} is a clam", ferris.name),
}
}
enum 的元素可以有一个或者多个数据类型,从而使其表现得像C语言中的联合。
当使用 match 对另一个 enum 进行模式匹配时,可以将变量名称绑定到每个数据值。
enum 的内存细节:
其他细节
#![allow(dead_code)]
enum Species { Crab, Octopus, Fish, Clam }
enum PoisonType { Acidic, Painful, Lethal }
enum Size { Big, Small }
enum Weapon {
Claw(i32, Size),
Poison(PoisonType),
None
}
struct SeaCreature {
species: Species,
name: String,
arms: i32,
legs: i32,
weapon: Weapon,
}
fn main() {
// SeaCreature's data is on stack
let ferris = SeaCreature {
// String struct is also on stack
// but holds a reference to data on heap
species: Species::Crab,
name: String::from("Ferris"),
arms: 2,
legs: 4,
weapon: Weapon::Claw(2, Size::Small)
};
match ferris.species {
Species::Crab => {
match ferris.weapon {
Weapon::Claw(num_claws, size) => {
let size_description = match size {
Size::Big => "big",
Size::Small => "small",
};
println!("ferris is a crab with {} {} claws", num_claws, size_description)
},
_ => println!("ferris is a crab with some other weapon")
}
}
},
_ => println!("ferris is some other animal"),
}
}