Updated src/structs/method_syntax.md'.

This commit is contained in:
Hector PENG
2026-03-11 18:56:46 +08:00
parent 64e909c895
commit 1a521240e5
5 changed files with 28 additions and 20 deletions

View File

@@ -0,0 +1,6 @@
[package]
name = "method_demo"
version = "0.1.0"
edition = "2024"
[dependencies]

View File

@@ -0,0 +1,3 @@
fn main() {
println!("Hello, world!");
}

View File

@@ -31,7 +31,7 @@
- [使用结构体组织相关数据](Ch05_Using_Structs_to_Structure_Related_Data.md)
- [定义与实例化结构体](structs/defining_and_instantiating.md)
- [使用结构体的示例程序](structs/example_program.md)
- [方法语法](structs/method_syntax.md)
- [方法](structs/method_syntax.md)
- [枚举与模式匹配](Ch06_Enums_and_Pattern_Matching.md)
- [定义一个枚举](enums_and_pattern_matching/defining_an_enum.md)

View File

@@ -210,7 +210,7 @@ fn main() {
}
```
*清单 5-12添加派生出 `Debug` 特质的属性,并使用调试格式打印 `Rectangle` 的实例*
**清单 5-12**:添加派生出 `Debug` 特质的属性,并使用调试格式打印 `Rectangle` 的实例
现在当我们运行程序时,我们将不会收到任何报错,并且我们将看到以下输出:

View File

@@ -1,18 +1,14 @@
# 方法语法
# 方法
**Method Syntax**
方法与函数类似:我们以 `fn` 关键字和名字声明他们,他们可以有参数和返回值,并且他们包含一些在方法于别处被调用时运行的代码。与函数不同,方法定义在结构体(或枚举或特质对象,我们将在 [第 6 章](../Ch06_Enums_and_Pattern_Matching.md) 和 [第 18 章](../oop/trait_objects.md) 分别介绍他们)的上下文中,并且他们的第一个参数始终时 `self`,表示方法正于其上被调用的结构体实例。
*方法* 与函数类似:我们用 `fn` 关键字和一个名字,来声明方法,方法可以有参数和返回值,同时他们还包含一些代码,这些代码会在从其他地方调用该方法时运行。与函数不同的是,方法是在某个结构体(或某个枚举或特质对象,我们将在 [第 6 章](../Ch06_Enums_and_Pattern_Matching.md) 和 [第 17 章](../oop/trait_objects.md) 分别介绍)的上下文中定义的,而且方法的第一个参数,总是表示该方法被调用所在的结构体实例本身的 `self`
## 方法语法
我们来修改以 `Rectangle` 实例为参数的 `area` 函数,转而构造一个定义在 `Rectangle` 结构上的 `area` 方法,如下清单 5-13 中所示。
## 定义出方法
**Defining Methods**
如下清单 5-13 所示,我们来修改以 `Rectangle` 实例为参数的那个 `area` 函数,转而构造出一个定义在 `Rectangle` 结构上的 `area` 方法。
<a name="listing_5-13"></a>
文件名:`src/main.rs`
```rust
#[derive(Debug)]
@@ -39,18 +35,21 @@ fn main() {
}
```
*清单 5-13:在 `Rectangle` 结构体上定义一个 `area` 方法*
**清单 5-13**:定义 `Rectangle` 结构体上`area` 方法
为了在 `Rectangle` 的上下文中定义函数,我们开始了个 `Rectangle``impl`实现implementation代码块。这个 `impl` 代码块中的所有内容都将与 `Rectangle` 类型关联。然后,我们将 `area` 函数移入 `impl` 的花括号中,并把函数签名中的第一个(本示例中的唯一)参数修改为 `self` 并修改函数体中的各处。在 `main` 中,在我们曾调用 `area` 函数并将 `rect1` 作为参数传递的地方,我们便可使用 *方法语法method syntax*,调用咱们 `Rectangle` 实例上的 `area` 方法。方法语法位于实例之后:我们添加一个点,后跟方法名称、圆括号及任何的参数。
`area` 的签名中,我们使用 `&self` 而不是 `rectangle: &Rectangle``&self` 实际上是 `self&Self` 的缩写。在 `impl` 代码块中,类型 `Self` 是该 `impl` 代码块所针对类型的别名。方法必须以名为 `self` 的类型 `Self` 参数作为其第一个参数,因此 Rust 允许咱们在第一个参数处可仅以名字 `self` 缩写这一参数。请注意,我们仍然需要在 `self` 简写前使用 `&`,表明这个方法借用 `Self` 实例,就像在 `rectangle: &Rectangle` 中所做的那样。方法可以取得 `self` 的所有权;或不可变地借用 `self`,就像我们在这里所做的那样;或者可变地借用 `self`,就像他们可以借用任何别的参数那样。
为了在 `Rectangle` 上下文中定义这个函数,我们为 `Rectangle` 创建了一个 `impl`implementation实现代码块。该 `impl` 代码块中的所有内容,都将与 `Rectangle` 这个类型相关联。然后,我们将那个 `area` 函数,移入 `impl` 的花括号中,并把函数签名中的首个(且本示例中唯一的)参数修改为 `self` 同时修改函数体中的各处。在 `main` 中,在我们曾调用过 `area` 函数并将 `rect1` 作为参数传递的地方,我们便可以使用 *方法语法method syntax*,在咱们的 `Rectangle` 实例上,调用 `area` 方法。方法语法位于某个实例之后:我们要添加一个后跟方法名称、圆括号和任何参数的一个点。
`area` 的签名中,我们使用了 `&self` 而不是 `rectangle: &Rectangle``&self` 实际上是 `self&Self` 的缩写。在 `impl` 代码块中,`Self` 这个类型,是 `impl` 代码块,所针对的那个类型的别名。方法必须将名为 `self`,类型为 `Self` 的参数,作为其第一个参数,因此 Rust 允许咱们,在第一个参数处,将其缩写为仅 `self` 这个名字。请注意,就像在 `rectangle: &Rectangle` 中一样,我们仍然需要在 `self` 这个简写前面,使用 `&` 来表明该方法借用了 `Self` 这个实例。方法可以取得 `self` 的所有权,也可以不可变借用 `self`(就像我们在这里所做的),还可以可变地借用 `self`(就像借用其他参数一样)。
> **译注**
>
> - `&self` - 不可变借用
> - `&mut self` 可变借用;
> - `self` - 取得所有权,发生所有权转移,`self` 所指向的内存堆上值,原先那个在栈上的变量将失效。
> **译注**`&self` - 不可变借用;`&mut self` 可变借用;`self` - 取得所有权,发生所有权转移,`self` 所指向的内存堆上值,原先那个在栈上的变量将失效
我们在这里选择 `&self` 的原因,与我们在函数那个版本中使用 `&Rectangle` 的原因相同:我们不打算取得所有权,我们只想读取该结构体中的数据,而不是向其写数据。如果我们打算修改调用方法的实例(作为该方法的一部分),我们可以使用 `&mut self` 作为第一个参数。只使用 `self` 作为第一个参数,来取得实例所有权的方法并不多见;这种方法通常用于该方法会将 `self` 转换成其他东西,且咱们想要防止调用者,在这种转换后继续使用原始实例的时候。
出于我们在函数版本中使用 `&Rectangle` 的同一原因,我们在这里选择 `$self`:我们不打算取得所有权,我们只想读取结构体中的数据,而不是写入他。若作为方法执行内容的一部分,咱们打算修改我们于其上调用方法的实例时,我们就要使用 `&mut self` 作为第一个参数。通过只使用 `self` 作为第一个参数让方法取得实例的所有权很少见;这种做法通常会在方法会将 `self` 转换成其他内容,而咱们打算阻止调用者在转换后使用原始实例时用到
除了提供方法语法和不必在每个方法的签名中,重复 `self` 的类型外,使用方法而不是函数的主要原因,是为了组织。我们把所有能用类型实例做的事情,都放在一个 `impl` 块中,而不是让我们代码的未来用户,在我们提供的库中不同地方,检索 `Rectangle` 的功能。