rust 结构体

Created

2024-05-14 09:15:38

Updated

2024-10-27 09:18:40

1 三种形式

1.1 经典的C语言风格结构体

C struct

#[derive(Debug)]
struct User {
    active: bool,
    username: String,
    email: String,
    sign_in_count: u64,
}

fn main() {
    let mut u = build_user("username123".to_string(), "someone@example.com".to_string());

    println!("{}", u.email);
    u.active = false;
    println!("{}", u);

    let u1 = build_user("u1@hotmail".to_string(), "u1".to_string());
    let u2 = User {
        email: String::from("u2@hotmail"),
        // 作为 base struct 必须放在最后, 否则是报错的
        // base struct 会使用剩余没设置值的字段
        // 所以注意这里u1 的 name被move 进来了.
        ..u1
    };
    println!("{:?}", u2);
    println!("{:#?}", u2); // 更加直观的打印

    // 因为u1.name 被move 了,所以会报错
    // println!("{:?}", u1); 
    println!("{:?}", u1.email); // email 还是可以打印的.

}
fn build_user(email: String, username: String) -> User {
    User { // 每个字段都必须设置值, 否则报错
        active: true,
        username, //  如果和结构体的字段同名, 可以直接这样简化写法
        email,    //  
        sign_in_count: 1,
    }
}

1.2 元祖结构体

Tip
  • tuple struct
  • 只有字段的类型,没有name
// 虽然元素类型一样, 但是2个结构体是不同的类型
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);

fn main() {
    let black = Color(0, 0, 0);
    let origin = Point(0, 0, 0);
    // 同元祖访问
    println!("{}", black.0);
}

1.3 单元结构体

unit struct, 没有字段的结构体


struct AlwaysEqual;

fn main() {
    // 实例化了
    let subject = AlwaysEqual;
}

2 方法和关联函数

#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}
// impl 块里的所有东西都和 Rectangle 类型产生关联
impl Rectangle {
    // 第一个参数是 &self 是 self: &Self的简写, 是不可变借用
    // 如果想用 所有权的, 就 用 self 是 self: Self的简写
    // 如果想用可变借用 就用&mut self 是self: &mut Self 的简写
    // 调用方法实际上是将调用者作为第一个参数传递给方法
    fn area_borrows_immutably(&self) -> u32 {
        println!(" width... {}", (*self).width);
        self.width * self.height
    }

    fn area_move(self) -> u32 {
        println!(" width... {}", self.width);
        self.width * self.height
    }
    fn area_borrows_mutably(&mut self) -> u32 {
        println!(" width... {}", (*self).width);
        self.width * self.height
    }

    fn change_width(&mut self, width: u32) {
        self.width = width;
    }

    // 关联函数
    // 例子: 正方形 ,这里没有用到 &self 作为第一个参数
    fn square(size: u32) -> Self {
        Self {
            width: size,
            height: size,
        }
    }
    // rust没有专门的构造函数,需要自己定义,我们一般用new 这个方法名,
    pub fn new(width: u32, height: u32) -> Self {
        Rectangle {
            width,
            height,
        }
    }
}

fn main() {
    let rect1 = Rectangle {
        width: 30,
        height: 50,
    };
    println!("{}", rect1.area_borrows_immutably());  // <1>
    println!("{:?}", rect1);
    println!("{}", rect1.area_move());
    // 报错, move掉了, 说明 我们的结构体是move 属性的,
    // println!("{:?}", rect1);
    let mut rect1 = Rectangle {
        width: 30,
        height: 50,
    };
    println!("{}", rect1.area_borrows_mutably());

    let mut rect2 = Rectangle {
        width: 30,
        height: 50,
    };
    // 调用的时候根据方法的第一个参数类型,会自动转为 比如 可变借用
    rect2.change_width(35);
    println!("{}", rect2.area_borrows_immutably());

    // 这样的方式调用
    let r = &mut rect2;
    Rectangle::change_width(r, 40);
    println!("{}", r.height);
    println!("{}", rect2.area_borrows_immutably());

    // 使用 :: 来调用
    let sq = Rectangle::square(3);
    println!("{}", sq.area_borrows_immutably());
}
  1. rect1.area_borrows_immutably()这个其实只是语法糖, 实际上是Rectangle::area_borrows_immutably(&rect1)
Back to top