所有在 impl 块中定义的函数被称为 关联函数(associated functions),因为它们与 impl 后面命名的类型相关。我们可以定义不以 self 为第一参数的关联函数(因此不是方法),因为它们并不作用于一个结构体的实例。我们已经使用了一个这样的函数:在 String 类型上定义的 String:: from 函数。 不是方法的关联函数经常被用作返回一个结构体新实例的构造函数,例如我们可以提供一个关联函数,它接受一个维度参数并且同时作为宽和高,这样可以更轻松的创建一个正方形 Rectangle 而不必指定两次同样的值:
# 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);
# }
使用结构体名和 :: 语法来调用这个关联函数:比如 let sq = Rectangle::square(3);。这个方法位于结构体的命名空间中: :: 语法用于关联函数和模块创建的命名空间。第七章会讲到模块。 多个 impl 块 每个结构体都允许拥有多个 impl 块。
# struct Rectangle {
# width: u32,
# height: u32,
# }
#
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
}
}
#
# 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 块中,不过这是有效的语法。第十章讨论泛型和 trait 时会看到实用的多 impl 块的用例。 总结 结构体让你可以创建出在你的领域中有意义的自定义类型。通过结构体,我们可以将相关联的数据片段联系起来并命名它们,这样可以使得代码更加清晰。在 impl 块中,你可以定义与你的类型相关联的函数,而方法是一种相关联的函数,让你指定结构体的实例所具有的行为。 但结构体并不是创建自定义类型的唯一方法:让我们转向 Rust 的枚举功能,为你的工具箱再添一个工具。