Rust struct


struct 结构体

自定义的数据类型,为相关联的值命名,打包成有意义的组合。

类似python的dict,但是赋值的时候可以不按顺序。初始化的时候一定要全部赋值完,不能缺少。先要创建结构体,再实例化结构体。

取值时使用点标记法。修改结构体里的值必须要求结构体是可变的 mut。一旦struct的实例是可变的,那么实例中的所有字段都是可变的。

fn main(){
    struct User{
        username: String,
        email: String,
        password: u64,
    }

    let mut achu = User{
        // 可以不按顺序赋值,但是不能缺字段
        email: String::from("achu@achu.com"),
        username: String::from("achu"),
        password: 123,
    };
}

字段初始化简写

当字段名和字段值对应的变量相同时,就可以使用字段初始化简写的方式。
struct 可以作为函数的返回值。

struct User{
    username: String,
    email: String,
    password: u64,
}

// User可以作为单独一种类型返回,因为它是结构体
fn makeUser(email: String, username: String) -> User{
    // 这里接收的值和struct里的值是一样的。
    User {
        email,
        username,
        password: 123
    }
}

struct 更新

基于某个struct实例来创建一个新的实例的时候,可以使用struct更新语法。

有相同的值时

fn main(){
    struct User{
        username: String,
        email: String,
        password: u64,
    }

    let mut achu = User{
        // 可以不按顺序赋值,但是不能缺字段
        email: String::from("achu@achu.com"),
        username: String::from("achu"),
        password: 123,
    };

    let mut afeng = User{
        email: String::from("afeng@achu.com"),
        username: String::from("afeng"),
        // password: achu.password, 等价于: ..achu
        ..achu
    };
    println!("{}", achu.email);
}

tuple struct

tuple struct 整体有个名,但是里面的元素没有名字。适用于整个tuple起名,并让它不同于其他的tuple,而且又不需要给每个元素起名。

struct Color(i32, i32, i32);
let black = Color(0, 0, 0);

unit-Like Struct 空结构体

定义没有任何字段的结构体,适用于需要在某个类型上实现某个trait,但是在里面又没有想要的存储的数据。

struct 数据的所有权

  • struct实例是有效的,那么里面的字段数据也是有效的。
  • struct可以存放应用,需要生命周期。不用就会报错。

结构体必须掌握字段值所有权,因为结构体失效的时候会释放所有字段。

结构体没有实现std::fmt::Display方法,结构体有不确定性,所以不能直接println!("{}")。
解决方法:使用println!("{:?}")或者println!("{:#?}"),但是要加debug模式(类似装饰器)#[derive(Debug)]

fn main() {
    #[derive(Debug)]
    struct User{
        username: String,
        email: String,
        password: u64,
    }

    let mut achu = User{
        // 可以不按顺序赋值,但是不能缺字段
        email: String::from("achu@achu.com"),
        username: String::from("achu"),
        password: 123,
    };
    println!("{:?}", achu);
    // 更加方便看,加个#
    println!("{:#?}", achu);
}

struct 方法

可以把struct看做一个类,而方法就是这个类中的方法(类似python)
方法和函数类似:fn关键字,名称,参数和返回值。

方法和函数的区别:

  • 方法是在struct,enum或trait对象的上下文中定义的。
  • 第一个参数是self, 标识方法被调用的struct的实例。

方法的self可以是可变的。也可以获得其所有权或可变借用,和其他参数一样。

// impl structName
impl User {
    fn makeUserZero(userModule: &User) -> u64{
        println!("user create success!");
        userModule.password
    }

    // 实例本身是第一个参数,所以self也不用手动传
    fn makeUserOne(&self) -> u64 {
        println!("user create success!");
        self.password
    }
}

关联函数

不把self作为第一个参数的函数,叫做关联函数(不是方法,但是与这个类型由关联)。类似python的类静态方法。

  • eg: String::from()

关联函数通常用于构造器。也就是创造被关联类型的一个实例。

调用的方法是::,两个冒号

可以创造多个impl块

方法传参

当一个实例化的结构体对象调用它的结构体方法时,可以传入另外一个结构体对象。

在调用方法时:rust根据情况自动添加&、&mut或*,以便object可以匹配方法的签名。
p1.dispatch(&p2);
(&p1).dispatch(&p2);
这两行代码是一样的。