方法

方法与函数类似,它使用 fn 关键字和名称声明,可以拥有参数和返回值,同时包含在某处调用该方法时会执行的代码。不过方法与函数不同的是,它们在结构体(枚举或 trait 对象)的上下文中被定义。并且它们第一个参数名总是 self。它代表调用该方法的结构体实例。

&selfself: &Self 的缩写 Selfimpl 类型的别名。self 参数支持所有借用规则,可以转移所有权,可以不可变借用,也可以可变借用。

fn rect_var() {
    let width1 = 30;
    let height1 = 20;
    println!("The area of Rectangles is {}", area(width1, height1));
}
fn area(width: u32, height: u32) -> u32 {
    return width * height;
}

fn rect_tuple() {
    let rect = (30, 40);
    println!("The area of Rectangles is {}", area_tuple(rect));
}

fn area_tuple(rectangles: (u32, u32)) -> u32 {
    return rectangles.0 * rectangles.1;
}

#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    fn area(&self) -> u32 { // &self 是 self: &Self 的缩写 Self 是 impl 类型的别名
        self.height * self.width
    }

    fn area_full(self: &Self) -> u32 {
        self.height * self.width
    }
}

fn rect_struct() -> Rectangle {
    let rect = Rectangle {
        width: 30,
        height: 50,
    };

    println!("{}", area_struct(&rect));
    println!("{:?}", rect);
    println!("{:#?}", rect);
    dbg!(rect)
}

fn area_struct(rect: &Rectangle) -> u32 {
    rect.width * rect.height
}

fn rect_method() {
    let rect = Rectangle {
        width: 20,
        height: 30,
    };

    println!("rect_method area: {}", rect.area());
    println!("rect_method area_full: {}", rect.area_full());
}

fn main() {
    rect_var();
    rect_tuple();
    rect_struct();
    rect_method();
}

关联函数

所有在 impl 块中定义的函数被称为关联函数,因为它们与 impl 后面命名的类型相关。我们可以定义不以 self 为第一个参数的关联函数。因为它们并不作用一个结构体的实例。

不是方法的关联函数经常被用作返回一个结构体新实例的构造函数。这些函数的名称通常为 new

使用结构体名和 :: 来调用这个关联函数。

#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}

impl Rectangle {
    fn square(size: u32) -> Rectangle {
        Self{
            width:size,
            height:size,
        }
    }
}
fn main() {
    println!("square is {:#?}", Rectangle::square(2));
}

每个结构体都可以拥有多个 impl 块。