Rust - 结构体
1、结构体
1.1、结构体的定义
- struct,结构体
- 自定义的数据类型
- 在花括号内,为所有字段定义名称和类型
// 定义struct
struct User{
username:String,
email:String,
sign_in_count:u64,
active:bool,
}
fn main() {
println!("Hello, world!");
}
1.2、实例化结构体
- 想要使用struct,需要创建其实例
- 为每个字段指定具体值
- 无需按照声明的顺序进行指定
// 定义struct
struct User{
username:String,
email:String,
sign_in_count:u64,
active:bool,
}
fn main() {
println!("Hello, world!");
// 定义了几个属性,就要实例化几个
let ren = User{
username:String::from("小明"),
email:String::from("admin@gmail"),
sign_in_count:19,
active:true,
};
}
1.3、获取结构体中的字段
-
一旦要结构体中某个值可变,那么都所有字段都是要可变的
-
取得struct里面某个值
- 使用点标记法
// 定义struct
struct User{
username:String,
email:String,
sign_in_count:u64,
active:bool,
}
fn main() {
println!("Hello, world!");
// 定义了几个属性,就要实例化几个
let mut ren = User{
username:String::from("小明"),
email:String::from("admin@gmail"),
sign_in_count:19,
active:true,
};
// 通过点访问属性
ren.username = String::from("小红");
}
1.4、Struct作为函数的返回值
// 定义 User 结构体
struct User {
username: String,
email: String,
sign_in_count: u64,
active: bool,
}
// 定义 build_user 函数,它接受两个字符串并返回一个 User 实例
fn build_user(email: String, username: String) -> User {
User {
username, // 等同于 username: username
email, // 等同于 email: email
sign_in_count: 1,
active: true, // 使用具体的值 true 来初始化布尔类型
}
}
1.5、Struct更新语法
- 当想基于某个struct实例来创建一个新的实例的时候,可以使用struct更新语法
#[derive(Debug)]
struct User {
username: String,
email: String,
sign_in_count: u64,
active: bool,
}
fn create_user_with_new_email(user: &User, new_email: String) -> User {
User {
email: new_email, // 提供一个新的 email 字段值
..*user // 其他字段从 user 参数中的现有实例复制
}
}
fn main() {
let user1 = User {
username: String::from("user123"),
email: String::from("[email protected]"),
sign_in_count: 1,
active: true,
};
let user2 = create_user_with_new_email(&user1, String::from("[email protected]"));
println!("User1: {:?}", user1);
println!("User2: {:?}", user2); // user2 将具有与 user1 相同的字段除了 email
}
1.6、Tuple struct
- 可定义类似tuple 的 struct,叫做tuple struct
- tuple struct整体有个名,但里面的元素没有名
- 适用于:想给整个tuple起名,并让它不同于其他tuple,而且又不需要给每个元素起名
struct Color(i32,i32,i32);
struct Point(i32,i32,i32);
fn main(){
let black = Color(0,0,0);
let origin = Point(0,0,0);
}
1.7、Unit-Like Struct(空结构体)
- 可以定义没有任何字段的结构体
- 适用于需要在某个类型上实现某个接口,但是在里面又没有想要存储的数据
1.8、struct数据的所有权
- 这里的字段使用了String而不是&str
- 该struct实例拥有其所有的数据
- 只要struct实例是有效的,那么里面的字段数据也是有效的
struct User {
username: String,
email: String,
sign_in_count: u64,
active: bool,
}
1.9、Struct的方法
- 方法和函数类似:fn关键字、名称、参数、返回值
- 方法和函数的不同之处
- 方法是在struct(或enum、trait对象)的上下文中定义
- 方法第一个参数是self,表示方法被调用的struct实例
- 在impl块中定义方法
#[derive(Debug)]
struct Rectangle{
width : u32,
length : u32,
}
// 定义方法
impl Rectangle {
fn area(&self) -> u32{
self.width * self.length
}
}
fn main() {
let rect = Rectangle{
width : 30,
length : 50,
};
println!("{}",rect.area());
// 格式化输出
println!("{:#?}",rect);
}
1.10、多个参数方法
#[derive(Debug)]
struct Rectangle{
width : u32,
length : u32,
}
// 定义方法
impl Rectangle {
fn area(&self) -> u32{
self.width * self.length
}
fn can_hold(&self,other:&Rectangle) -> bool{
self.width > other.width && self.length > other.length
}
}
fn main() {
let rect = Rectangle{
width : 30,
length : 50,
};
let rect1 = Rectangle{
width : 10,
length : 40,
};
let rect2 = Rectangle{
width : 35,
length : 52,
};
println!("{}",rect.area());
// 格式化输出
println!("{:#?}",rect);
// 调用多个方法的函数
println!("{}",rect.can_hold(&rect1));
println!("{}",rect.can_hold(&rect2));
}
1.11、关联函数
- 可以在impl块里定义不把self作为第一参数的函数,它们叫关联函数
- 关联函数通常用于构造器
#[derive(Debug)]
struct Rectangle{
width : u32,
length : u32,
}
// 定义方法
impl Rectangle {
// 定义关联函数
fn square(size:u32)->Rectangle{
Rectangle {
width: size,
length: size
}
}
}
fn main() {
// 调用关联函数 名:函数名
let s = Rectangle::square(20);
}
推荐阅读: