这篇博客来聊一下 结构体的方法
,本质上就是为某个结构体而定义的方法 (函数)。拿面向对象语言来说,写了一个类,还可能会在这个类里写一些方法,基本上同样的套路。或者说,定义的这些方法,是与这个结构体有关的。
不太严谨的解释,这里所谓的方法,其实就是一个函数。
结构体方法的定义
看下面的代码
// 这里定义一个矩形的结构体
#[derive(Debug)]
struct Rectangle {
width: u32,
height: u32,
}
// 这里的 impl xxx 是固定的,xxx 就是你要为哪一个结构体去定义一些方法
impl Rectangle {
// 这是一个计算面积的方法
fn area(&self) -> u32 {
self.width * self.height
}
// 这是一个计算周长的方法
fn perimeter(&self) -> u32 {
self.width * 2 + self.height * 2
}
// 这是一个计算能否包含另一个矩形的方法
fn can_hold(&self, other: &Rectangle) -> bool {
self.width > other.width && self.height > other.height
}
}
!!! 注意看上面的代码及 注释
结构体的
方法
第一个参数总是&self
表示定义好的结构体实例
自身
下面是使用这个结构体
fn main() {
let r1 = Rectangle {width: 128, height: 90};
let r2 = Rectangle {width: 50, height: 30};
println!("{:#?}", r1);
println!("{:#?}", r2);
// 调用结构体的 area() 方法
println!("r area: {}", r1.area());
// 调用结构体的 perimeter() 方法
println!("r perimeter: {}", r1.perimeter());
// 调用结构体的 can_hold() 方法
println!("r1 can hold r2: {}", r1.can_hold(&r2));
}
注意上面的代码,我们打印结构体实例的时候,以前是用
{:?}
,而这次用的是{:#?}
。这是因为,使用{:#?}
能以更美观的方式打印出这个结构体的数据来
如果要定义可以修改的结构体,只要加上 mut
就行,看下面的代码
fn main() {
let mut r1 = Rectangle {width: 100, height: 50};
println!("{:#?}", r1);
// 修改了 r1 的 width
r1.width = 1000;
println!("{:#?}", r1);
}
关联函数
在 impl
代码块中,定义一些不以 &self
作为参数的函数,这些函数被称为 关联函数
。就是说,这些函数,不针对某一个具体的结构体实例,而是针对这个结构体本身。
直接看下面的代码
#[derive(Debug)]
struct Rectangle {
width: u32,
height: u32,
}
impl Rectangle {
// 创建一个 矩形 实例
fn new(width: u32, height: u32) -> Rectangle {
Rectangle {
width,
height,
}
}
// 创建一个 正方形 实例
fn new_square(size: u32) -> Rectangle {
Rectangle {
width: size,
height: size,
}
}
}
下面代码是 使用
关联函数
fn main() {
let r1 = Rectangle::new(100, 80);
let r2 = Rectangle::new_square(100);
println!("{:#?}", r1);
println!("{:#?}", r2);
}
对于一个结构体方法的调用,我们使用
r1.area()
这样的形式。而对于关联函数
的调用,需要使用::
这个操作符。