4.9 KiB
Method Syntax
方法与函数类似:我们使用fn关键字和名称来声明它们,它们可以有参数和返回值,并且在从其他地方调用方法时会运行一些代码。与函数(独立的代码块,它可以在任何地方被调用)不同的是,方法在结构体的上下文中定义,它们的第一个参数总是self,表示调用方法的结构体的实例。
为了在 Rectangle 的上下文中定义函数,我们为 Rectangle 开始一个 impl(实现)块。此 impl 块中的所有内容都将与 Rectangle 类型相关联。然后,将 area 函数移动到 impl 大括号内,并在签名和函数体内的所有位置将第一个(在这种情况下,仅有)参数更改为 self。
&self实际上是
self: &Self。
方法的第一个参数必须命名为 self。 self 的类型必须是 Self。写&self而不是self(可以写),原因与在函数版本中使用 &Rectangle 相同:我们不想拥有所有权,只想读取结构体中的数据,而不是写入它。如果我们想在方法执行时更改调用方法的实例,则应使用 &mut self 作为第一个参数。拥有 self 的方法很少使用;通常使用此技术是因为方法将 self 转换为其他内容,并且您希望防止调用者在转换后使用原始实例。
使用方法而不是函数的主要原因,除了提供方法语法并且无需在每个方法的签名中重复 self 类型之外,还是为了组织。我们将所有可以使用类型实例的内容放在一个 impl 块中。
getters
方法名可以与字段名相同,当我们提供与字段同名的方法时,我们希望它只返回字段中的值而不做任何其他事情。像这样的方法称为getters,Rust 不会像其他一些语言那样自动为结构字段实现它们。Getters 很有用,因为您可以将字段设为私有,但将方法设为公开,从而作为类型的公共 API 的一部分启用对该字段的只读访问:
-> Operator
Rust 没有等价于 -> 运算符的东西;相反,Rust 有一个称为自动引用和解除引用的功能。调用方法是 Rust 中拥有此行为的少数地方之一。仅适用于方法的接收者,意思就是如果方法参数接的是&self,你直接穿rect也可以,会隐式转为&rect。有了这个特征,传方法直接无脑传就行。接收者来决定穿的具体模式
这是它的工作方式:当使用 object.something() 调用方法时,Rust 会自动添加 &、&mut 或 *,使 object 与方法的签名匹配。换句话说,以下内容是相同的:
p1.distance(&p2); (&p1).distance(&p2); 第一个看起来要干净得多。这种自动引用行为之所以能够工作,是因为方法具有明确的接收者——self 的类型。 给定方法的接收者和名称,Rust 可以明确地确定方法是读取(&self)、修改(&mut self)还是消耗(self)。 Rust 将借用隐式应用于方法接收者的事实是使所有权在实践中更加容易。
图1
图2
图3
更多参数的方法
相关函数
在 impl 块内定义的所有函数都被称为关联函数,因为它们与 impl 后面的类型相关联。我们可以定义没有 self 作为第一个参数的关联函数(因此不是方法),因为它们不需要类型的实例才能工作。我们已经使用了一个类似的函数:String::from 函数,它定义在 String 类型上。
非方法的关联函数通常用作构造函数,它们将返回 struct 的新实例。这些函数通常被称为 new,但 new 不是一个特殊的名称,也不是内置在语言中的。
多个impl
首先,可以使用多个 impl 块来定义不同的行为,其中每个 impl 块定义一组功能。这可以使类型的实现更加清晰,并使代码更容易阅读和维护。
其次,可以使用多个 impl 块来分离相关的功能,并使用不同的 impl 块来实现某个 trait 的不同版本。这可以让类型具有更多的灵活性,并允许更好地适应变化。