写点什么

Rust 从 0 到 1- 结构体 - 方法

用户头像
关注
发布于: 2021 年 04 月 09 日
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()    );}
复制代码

与函数不同的是,在 area 方法的参数中,使用 &self 来替代 rectangle: &Rectangle,该方法位于结构体 Rectangle 上下文中,Rust 知道 self 的类型是 Rectangle。注意,self 前面的 & 和 &Rectangle 一样是对结构体的引用。这个和函数的参数一样,可以选择获取 self 的所有权,或者引用。如果想要在方法中改变实例,需要将第一个参数改为 &mut self。仅仅使用 self 作为第一个参数来使方法获取实例的所有权是很少使用的,通常用在当方法将 self 转换成别的实例,同时防止再调用方法后还使用原始的实例。

使用方法替代函数,除了可使用方法语法和不需要在每个函数参数中重复 self 的类型之外,其主要好处在于组织性。我们将某个类型实例能做的所有事情都一起放入 impl 中,而不是让用户在我们的库中到处寻找 Rectangle 的功能(这个感觉是借鉴了面向对象的思想)。

增加更多参数

下面通过实现 Rectangle 结构体上的另一方法来作为例子。这个方法(can_hold)实现以下逻辑:如果当前矩形能完全包含另一个矩形则返回 true;否则返回 false:

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    }}
复制代码

在方法参数中可以在 self (必须是第一个参数)后增加多个参数,就像函数中的参数一样。

关联函数

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 的枚举类型。

发布于: 2021 年 04 月 09 日阅读数: 14
用户头像

关注

公众号"山 顽石"欢迎大家关注;) 2021.03.23 加入

IT老兵,关注Rust、Java、前端、架构、大数据、AI、算法等;平时喜欢美食、旅游、宠物、健身、篮球、乒乓球等。希望能和大家交流分享。

评论

发布
暂无评论
Rust从0到1-结构体-方法