Rust从0到1-结构体-方法
结构体的方法与函数类似:都使用 fn 关键字声明,可以拥有参数和返回值,并且包含一段代码逻辑。不过与函数不同的是,它们在结构体的上下文中被定义(或者是 enum、trait 的上下文,在后续章节介绍),并且它的第一个参数是 self,它代表该方法对应的结构体实例。
定义方法
下面我们把前面计算矩形面积的 area 函数,改写成一个定义于 Rectangle 结构体上的方法:
#[derive(Debug)]
struct Rectangle {
width: u32,
height: u32,
}
impl Rectangle {
fn area(&self) -> u32 {
self.width * self.height
}
}
fn main() {
let rect1 = Rectangle {
width: 30,
height: 50,
};
println!(
"The area of the rectangle is {} square pixels.",
rect1.area()
);
}
与函数不同的是,在
使用方法替代函数,除了可使用方法语法和不需要在每个函数参数中重复
增加更多参数
下面通过实现 Rectangle 结构体上的另一方法来作为例子。这个方法(
impl Rectangle {
fn area(&self) -> u32 {
self.width * self.height
}
fn can_hold(&self, other: &Rectangle) -> bool {
self.width > other.width && self.height > other.height
}
}
在方法参数中可以在
关联函数
Rust还可以在 impl 块中定义不以 self 作为参数的函数,称为关联函数(associated functions)。它们是函数而不是方法,它们不默认使用结构体的实例作为参数使用。譬如,String::from 就是一个关联函数。
关联函数经常被用作结构体的构造函数。例如,我们可以提供一个关联函数,它接受一个参数同时作为宽和高,从而可以更加方便的创建一个正方形 Rectangle ,而不必重复写两次相同的值:
impl Rectangle {
fn square(size: u32) -> Rectangle {
Rectangle {
width: size,
height: size,
}
}
}
如果要调用关联函数,可以使用 :: 语法(后面章节会详细介绍),比如:
let sq = Rectangle::square(3);
多个 impl
每个结构体都允许拥有多个 impl 块:
impl Rectangle {
fn area(&self) -> u32 {
self.width * self.height
}
}
impl Rectangle {
fn can_hold(&self, other: &Rectangle) -> bool {
self.width > other.width && self.height > other.height
}
}
多个 impl 是有效的语法,但似乎没什么必要。后面在讨论 generic types 和 trait 时会介绍多 impl 块的使用场景。
总结
结构体在Rust中体现了面向对象的思想和特性:让我们可以创建出有含义的自定义类型,将相关联的数据联系起来并给与有意义的命名;而方法则允许为结构体实例实现特有的行为,关联函数则将和结构体相关的功能置于结构体的命名空间中。
结构体并不是创建自定义类型的唯一方法,下面将介绍Rust的枚举类型。