首页 技术杂谈 正文
  • 本文约3185字,阅读需16分钟
  • 188
  • 0

Rust - 结构体

摘要

Rust结构体,构建自定义数据类型的核心。它们定义了数据的蓝图,支持封装、实现方法,是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); 

}
评论