rust 结构体
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
1.3 单元结构体
unit struct, 没有字段的结构体
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());
}rect1.area_borrows_immutably()这个其实只是语法糖, 实际上是Rectangle::area_borrows_immutably(&rect1)