结构方法

要在结构上声明方法(即​​,可以在 struct 上调用的函数,或者 struct 类型的值),创建一个 impl 块:

impl Foo {
    fn fiddle(&self) {
        // "self" refers to the value this method is being called on
        println!("fiddling {}", self.my_string);
    }
}

// ...
foo.fiddle(); // prints "fiddling hello"

&self 这里表示对 struct Foo 实例的不可变引用是调用 fiddle 方法所必需的。如果我们想要修改实例(例如更改其中一个字段),我们将改为使用 &mut self(即可变引用):

impl Foo {
    fn tweak(&mut self, n: isize) {
        self.my_num = n;
    }
}

// ...
foo.tweak(43);
assert_eq!(foo.my_num, 43);

最后,我们还可以使用 self(注意缺少 &)作为接收器。这要求实例由调用者拥有,并且在调用方法时将导致实例被移动。如果我们希望使用,销毁或以其他方式完全转换现有实例,这将非常有用。这种用例的一个例子是提供链接方法:

impl Foo {
    fn double(mut self) -> Self {
        self.my_num *= 2;
        self
    }
}

// ...
foo.my_num = 1;
assert_eq!(foo.double().double().my_num, 4);

请注意,我们还将 selfmut 作为前缀,以便我们可以在再次返回之前改变自我。double 方法的返回类型也需要一些解释。impl 块内的 Self 指的是 impl 适用的类型(在本例中为 Foo)。在这里,它主要是避免重新键入类型的签名的有用简写,但在特征中,它可以用于引用实现特定特征的基础类型。

要为 struct 声明一个关联的方法 (在其他语言中通常称为类方法),只需省略 self 参数。这种方法在 struct 类型本身上调用,而不是在它的实例上调用:

impl Foo {
    fn new(b: bool, n: isize, s: String) -> Foo {
        Foo { my_bool: b, my_num: n, my_string: s }
    }
}

// ...
// :: is used to access associated members of the type
let x = Foo::new(false, 0, String::from("nil"));
assert_eq!(x.my_num, 0);

请注意,只能为当前模块中声明的类型定义结构方法。此外,与字段一样,默认情况下所有结构方法都是私有的,因此只能由同一模块中的代码调用。你可以使用 pub 关键字为定义添加前缀,以使其可以从其他位置调用。