方法 Method

2024/01/12

1. 定义方法

Rust 使用 impl 来定义方法,例如以下代码:

struct Circle { x: f64, y: f64, radius: f64, } impl Circle { // new是Circle的关联函数,因为它的第一个参数不是self,且new并不是关键字 // 这种方法往往用于初始化当前结构体的实例 fn new(x: f64, y: f64, radius: f64) -> Circle { Circle { x: x, y: y, radius: radius, } } // Circle的方法,&self表示借用当前的Circle结构体 fn area(&self) -> f64 { std::f64::consts::PI * (self.radius * self.radius) } }
rust

Rust和其它语言,例如Java中的类不同的是,impl只能用来定义方法,里面不能包括属性,而Java中的类既可以有方法,也可以有属性。
如果需要使用属性,需要搭配结构体使用。

如果implstruct的名称相同,则两者会被视作同一个:

#[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() ); }
rust

self、&self和&mut self

在上面 area`` 的签名中,我们使用&self替代rectangle: &Rectangle&self其实是self: &Self的简写(注意大小写)。在一个impl块内,Self指代被实现方法的结构体类型,self指代此类型的实例,换句话说,self指代的是Rectangle结构体实例,这样的写法会让我们的代码简洁很多,而且非常便于理解:我们为哪个结构体实现方法,那么self` 就是指代哪个结构体的实例。

需要注意的是,self 依然有所有权的概念:

  • self 表示 Rectangle 的所有权转移到该方法中,这种形式用的较少
  • &self 表示该方法对 Rectangle 的不可变借用
  • &mut self 表示可变借用

2. 关联函数

参数中不包含 self 的函数就是关联函数,注意是函数而不是方法。

impl Rectangle { fn new(w: u32, h: u32) -> Rectangle { Rectangle { width: w, height: h } } }
rust

在Rust中,并没有构造器的概念,也就是说构造一个对象并不一定需要调用new方法,而new方法在语法层面也并不代表构造器,只是一个
约定俗成的规则,Rust里使用new作为构造器的名称。

因为是函数,所以不能用.来调用,只能通过::来调用,例如String::from

3. 多个impl定义

Rust 允许我们为一个结构体定义多个 impl 块,目的是提供更多的灵活性和代码组织性,例如当方法多了后,可以把相关的方法组织在同一个 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 } }
rust

4. 为枚举实现方法

枚举类型之所以强大,不仅仅在于它好用、可以同一化类型,还在于,我们可以像结构体一样,为枚举实现方法:

#![allow(unused)] enum Message { Quit, Move { x: i32, y: i32 }, Write(String), ChangeColor(i32, i32, i32), } impl Message { fn call(&self) { // 在这里定义方法体 } } fn main() { let m = Message::Write(String::from("hello")); m.call(); }
rust