4.2 方法与关联函数
在 Rust 中,结构体本身只包含数据,不直接包含行为。要为结构体(或其他类型)添加方法或函数,需要使用 impl 块(implementation block)。通过 impl,你可以定义方法(method)和关联函数(associated function),从而将数据与操作逻辑组织在一起。
定义方法
方法是与特定类型关联的函数,其第一个参数通常是 self、&self 或 &mut self,表示调用该方法的实例。
例如,为之前定义的 Point 结构体添加一个计算到原点距离的方法:
struct Point {
x: f64,
y: f64,
}
impl Point {
fn distance_from_origin(&self) -> f64 {
(self.x.powi(2) + self.y.powi(2)).sqrt()
}
}
这里,&self 是 self: &Point 的简写,表示该方法借用当前实例进行只读访问。调用方式如下:
let p = Point { x: 3.0, y: 4.0 };
println!("Distance: {}", p.distance_from_origin()); // 输出 5.0
如果方法需要修改实例,则使用 &mut self:
impl Point {
fn move_by(&mut self, dx: f64, dy: f64) {
self.x += dx;
self.y += dy;
}
}
let mut p = Point { x: 0.0, y: 0.0 };
p.move_by(1.0, 2.0);
也可以使用 self(无引用)来获取实例的所有权,通常用于消耗性操作或转换:
impl Point {
fn to_tuple(self) -> (f64, f64) {
(self.x, self.y)
}
}
调用后,原变量将不再可用。
关联函数
关联函数是定义在 impl 块中但不以 self 作为参数的函数。它们类似于其他语言中的“静态方法”,常用于构造实例。
最常见的例子是 new 函数:
impl Point {
fn new(x: f64, y: f64) -> Point {
Point { x, y }
}
}
调用时使用类型名而非实例:
let p = Point::new(1.0, 2.0);
Rust 标准库中的许多类型都提供 new 或其他构造函数(如 String::from、Vec::with_capacity 等)。
为同一类型定义多个 impl 块
Rust 允许为同一个类型编写多个 impl 块,这在组织代码或条件编译时很有用:
impl Point {
fn x(&self) -> f64 {
self.x
}
}
impl Point {
fn y(&self) -> f64 {
self.y
}
}
虽然通常建议将相关方法放在同一个 impl 块中以提高可读性,但语法上是允许分散的。
小结
通过 impl 块,Rust 将数据(结构体)与行为(方法和关联函数)清晰地关联起来,同时保持所有权和借用规则的一致性。方法使你可以安全地操作实例数据,而关联函数则提供了灵活的构造方式。这种设计既支持面向对象风格的编程,又保留了函数式和系统级编程的灵活性,是 Rust 类型系统的重要组成部分。