原文:https://course.rs/basic/method.html
目录
定义方式
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) } }
#[derive(Debug)] struct Rectangle { width: u32, height: u32, } impl Rectangle { // 我们使用 &self 替代 rectangle: &Rectangle,&self 其实是 self: &Self 的简写(注意大小写) 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() ); }
self、&self 和 &mut self
self 依然有所有权的概念:
self
表示Rectangle
的所有权转移到该方法中,这种形式用的较少&self
表示该方法对Rectangle
的不可变借用&mut self
表示可变借用
方法名可以跟结构体字段名相同
在 Rust 中,允许方法名跟结构体的字段名相同:
impl Rectangle { fn width(&self) -> bool { self.width > 0 } } fn main() { let rect1 = Rectangle { width: 30, height: 50, }; if rect1.width() { println!("The rectangle has a nonzero width; it is {}", rect1.width); } }
一般来说,方法跟字段同名,往往适用于实现 getter 访问器,例如:
pub struct Rectangle { width: u32, height: u32, } impl Rectangle { pub fn new(width: u32, height: u32) -> Self { Rectangle { width, height } } pub fn width(&self) -> u32 { return self.width; } } fn main() { let rect1 = Rectangle::new(30, 50); println!("{}", rect1.width()); }
我们可以把 Rectangle 的字段设置为私有属性,只需把它的 new 和 width 方法设置为公开可见。
当使用 object.something() 调用方法时,Rust 会自动为 object 添加 &、&mut 或 * 以便使 object 与方法签名匹配。也就是说,这些代码是等价的:
p1.distance(&p2); (&p1).distance(&p2);
带有多个参数的方法
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 } } fn main() { let rect1 = Rectangle { width: 30, height: 50 }; let rect2 = Rectangle { width: 10, height: 40 }; let rect3 = Rectangle { width: 60, height: 45 }; println!("Can rect1 hold rect2? {}", rect1.can_hold(&rect2)); println!("Can rect1 hold rect3? {}", rect1.can_hold(&rect3)); }
关联函数
定义在 impl
中且没有 self
的函数被称之为关联函数,相当于其他语言中的static
方法。
impl Rectangle { fn new(w: u32, h: u32) -> Self { Rectangle { width: w, height: h } } }
Rust 中有一个约定俗成的规则,使用 new 来作为构造器的名称,出于设计上的考虑,Rust 特地没有用 new 作为关键字
因为是函数,所以不能用 . 的方式来调用,我们需要用 :: 来调用
多个 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 } }
为枚举实现方法
#[derive(Debug)] enum TrafficLightColor { Red, Yellow, Green, } // 为 TrafficLightColor 实现所需的方法 impl TrafficLightColor { fn color(&self) -> &str { match self { Self::Yellow => "yellow", _ => "" } } } fn main() { let c = TrafficLightColor::Yellow; assert_eq!(c.color(), "yellow"); println!("{:?}",c); }
注意,assert_eq!
的两个参数 String
和&str
可以互相比较。