解构方法语法

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

定义方法

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

// impl 是 implementation 的缩写
impl Rectangle {
    // 定义方法
    // 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()
    );
}

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

impl Rectangle {
    // 我们可以在 Rectangle 上定义一个方法,并命名为 width:
    fn width(&self) -> bool {
        self.width > 0
    }
}

fn main() {
    let rect1 = Rectangle {
        width: 30,
        height: 50,
    };

    // 在 main 中,
    // 当我们在 rect1.width 后面加上括号时。Rust 知道我们指的是方法 width。
    // 当我们不使用圆括号时,Rust 知道我们指的是字段 width。
    if rect1.width() {
        println!("The rectangle has a nonzero width; it is {}", rect1.width);
    }
}

带有更多参数的方法

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

// 所有在 impl 块中定义的函数被称为 关联函数(associated functions),
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 块中定义的函数被称为 关联函数(associated functions),因为它们与 impl 后面命名的类型相关。

我们可以定义不以 self 为第一参数的关联函数(因此不是方法),因为它们并不作用于一个结构体的实例。

String 类型上定义的 String::from 函数 就是这样的一个关联函数

不是方法的关联函数经常被用作返回一个结构体新实例的构造函数:

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

impl Rectangle {
    // 非方法的关联函数
    fn square(size: u32) -> Rectangle {
        Rectangle {
            width: size,
            height: size,
        }
    }
}

fn main() {
    let sq = Rectangle::square(3);
}

多个 impl 块

每个结构体都允许拥有多个 impl 块。

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

// impl 块1
impl Rectangle {
    fn area(&self) -> u32 {
        self.width * self.height
    }
}

// impl 块2
impl Rectangle {
    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));
}