05
结构体 Struct:Rust 的"类"
Struct · Methods · derive
Java 用 class 把数据和方法捆一起;Rust 把这俩拆开——结构体定义数据,impl 块定义方法。没有继承,但组合 + trait 一样能干活。
三种结构体
// 1) 经典具名字段结构体:对标 Java 的 POJO
struct User {
username: String,
age: u32,
active: bool,
}
// 2) 元组结构体:给一组数据起个类型名,字段没名字
struct Color(i32, i32, i32);
struct Point(f64, f64);
// 3) 类单元结构体:没有字段,常用于实现 trait 当标记
struct AlwaysEqual;
fn main() {
let u = User { username: String::from("张三"), age: 30, active: true };
println!("{} 岁", u.age);
let black = Color(0, 0, 0);
let _b = AlwaysEqual;
// 结构体更新语法:..other 把 other 里没写的字段搬过来
let u2 = User { age: 31, ..u }; // username/active 从 u 搬
println!("{}", u2.username);
}
方法与关联函数:impl 块
struct Rectangle { width: u32, height: u32 }
impl Rectangle {
// 方法:第一个参数永远是 self,&self 借用自己(最常见)
fn area(&self) -> u32 {
self.width * self.height
}
// &mut self:可变借用,能改自己;self:拿走所有权
fn scale(&mut self, k: u32) { self.width *= k; }
// 关联函数:没有 self 参数,相当于 Java 的静态方法,用 :: 调用
fn square(size: u32) -> Rectangle {
Rectangle { width: size, height: size }
}
}
fn main() {
let mut r = Rectangle { width: 3, height: 4 };
println!("面积 {}", r.area()); // 方法用点号调用
r.scale(2);
let s = Rectangle::square(5); // 关联函数用 :: 调用
println!("{} {}", r.width, s.area());
}
$ cargo run
面积 12
6 25
派生属性 derive:编译器帮你实现常见 trait
// 一行 derive,自动实现一堆常用 trait
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
struct Point { x: i32, y: i32 }
fn main() {
let p = Point { x: 1, y: 2 };
println!("{:?}", p); // Debug 派生后才能 {:?} 打印
let p2 = Point::default(); // Default 派生后有默认值
println!("{}", p == Point{x:1,y:2}); // PartialEq 派生后才能 ==
}
$ cargo run
Point { x: 1, y: 2 }
true
论字段可见性 pub
结构体的字段默认私有,别的模块看不见。想暴露就在字段前加 pub。方法同理——不过方法默认是"该类型自己的",对外暴露需要 pub fn。这跟 Java 的 private/public 一个道理。