mirror of
https://github.com/gnu4cn/rust-lang-zh_CN.git
synced 2026-08-19 12:43:28 +08:00
Updated src/structs/method_syntax.md'.
This commit is contained in:
6
projects/method_demo/Cargo.toml
Normal file
6
projects/method_demo/Cargo.toml
Normal file
@@ -0,0 +1,6 @@
|
||||
[package]
|
||||
name = "method_demo"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
3
projects/method_demo/src/main.rs
Normal file
3
projects/method_demo/src/main.rs
Normal file
@@ -0,0 +1,3 @@
|
||||
fn main() {
|
||||
println!("Hello, world!");
|
||||
}
|
||||
@@ -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)
|
||||
|
||||
@@ -210,7 +210,7 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
*清单 5-12:添加派生出 `Debug` 特质的属性,并使用调试格式打印 `Rectangle` 的实例*
|
||||
**清单 5-12**:添加派生出 `Debug` 特质的属性,并使用调试格式打印 `Rectangle` 的实例
|
||||
|
||||
|
||||
现在当我们运行程序时,我们将不会收到任何报错,并且我们将看到以下输出:
|
||||
|
||||
@@ -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` 的功能。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user