You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

4.9 KiB

Method Syntax

方法与函数类似:我们使用fn关键字和名称来声明它们,它们可以有参数和返回值,并且在从其他地方调用方法时会运行一些代码。与函数(独立的代码块,它可以在任何地方被调用)不同的是,方法在结构体的上下文中定义,它们的第一个参数总是self,表示调用方法的结构体的实例。

image-20230106092052958

为了在 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 的一部分启用对该字段的只读访问:

image-20230106094910062

-> 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

image-20230106100950035

图2

image-20230106101543144

图3

image-20230106102034323

更多参数的方法

image-20230106102924223

相关函数

在 impl 块内定义的所有函数都被称为关联函数,因为它们与 impl 后面的类型相关联。我们可以定义没有 self 作为第一个参数的关联函数(因此不是方法),因为它们不需要类型的实例才能工作。我们已经使用了一个类似的函数:String::from 函数,它定义在 String 类型上。

非方法的关联函数通常用作构造函数,它们将返回 struct 的新实例。这些函数通常被称为 new,但 new 不是一个特殊的名称,也不是内置在语言中的。

image-20230106113123490

多个impl

首先,可以使用多个 impl 块来定义不同的行为,其中每个 impl 块定义一组功能。这可以使类型的实现更加清晰,并使代码更容易阅读和维护。

其次,可以使用多个 impl 块来分离相关的功能,并使用不同的 impl 块来实现某个 trait 的不同版本。这可以让类型具有更多的灵活性,并允许更好地适应变化。

image-20230106114608539