From ba0e76f3dc27e3bf4df6df562cbadabcdc8f2716 Mon Sep 17 00:00:00 2001 From: Hector PENG Date: Sat, 21 Mar 2026 19:00:39 +0800 Subject: [PATCH] Updated src/generic_types_traits_and_lifetimes/generics.md'. --- projects/generic_func/Cargo.toml | 6 + projects/generic_func/src/main.rs | 31 +++++ projects/generic_method/Cargo.toml | 6 + projects/generic_method/src/main.rs | 22 ++++ projects/generic_struct/Cargo.toml | 6 + projects/generic_struct/src/main.rs | 17 +++ .../generics.md | 124 ++++++++---------- 7 files changed, 145 insertions(+), 67 deletions(-) create mode 100644 projects/generic_func/Cargo.toml create mode 100644 projects/generic_func/src/main.rs create mode 100644 projects/generic_method/Cargo.toml create mode 100644 projects/generic_method/src/main.rs create mode 100644 projects/generic_struct/Cargo.toml create mode 100644 projects/generic_struct/src/main.rs diff --git a/projects/generic_func/Cargo.toml b/projects/generic_func/Cargo.toml new file mode 100644 index 0000000..a622c7e --- /dev/null +++ b/projects/generic_func/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "generic_func" +version = "0.1.0" +edition = "2024" + +[dependencies] diff --git a/projects/generic_func/src/main.rs b/projects/generic_func/src/main.rs new file mode 100644 index 0000000..3f52981 --- /dev/null +++ b/projects/generic_func/src/main.rs @@ -0,0 +1,31 @@ +use std::cmp::PartialOrd; + +fn largest(list: &[T]) -> &T { + let mut largest = &list[0]; + + for item in list { + if item > largest { + largest = item; + } + } + + largest +} + +fn main() { + let number_list = vec! [34, 50, 25, 100, 65]; + + let result = largest(&number_list); + println! ("最大数为 {result}"); + + let char_list = vec! ['y', 'm', 'a', 'q']; + + let result = largest(&char_list); + println! ("最大字符为 {result}"); + + let str_list = vec! ["one", "two", "three"]; + + let result = largest(&str_list); + println! ("最大字符串为 {result}"); + +} diff --git a/projects/generic_method/Cargo.toml b/projects/generic_method/Cargo.toml new file mode 100644 index 0000000..be467fa --- /dev/null +++ b/projects/generic_method/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "generic_method" +version = "0.1.0" +edition = "2024" + +[dependencies] diff --git a/projects/generic_method/src/main.rs b/projects/generic_method/src/main.rs new file mode 100644 index 0000000..4e8d593 --- /dev/null +++ b/projects/generic_method/src/main.rs @@ -0,0 +1,22 @@ +struct Point { + x: T, + y: T, +} + +impl Point { + fn x(&self) -> &T { + &self.x + } +} + +impl Point { + fn distance_from_origin(&self) -> f32 { + (self.x.powi(2) + self.y.powi(2)).sqrt() + } +} + +fn main() { + let p = Point { x: 5, y: 10 }; + + println!("p.x = {}", p.x()); +} diff --git a/projects/generic_struct/Cargo.toml b/projects/generic_struct/Cargo.toml new file mode 100644 index 0000000..53e2b6c --- /dev/null +++ b/projects/generic_struct/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "generic_struct" +version = "0.1.0" +edition = "2024" + +[dependencies] diff --git a/projects/generic_struct/src/main.rs b/projects/generic_struct/src/main.rs new file mode 100644 index 0000000..232f919 --- /dev/null +++ b/projects/generic_struct/src/main.rs @@ -0,0 +1,17 @@ +#[derive(Debug)] +struct Point { + x: T, + y: U, +} + +fn main() { + let both_integer = Point { x: 5, y: 10 }; + let both_float = Point { x: 1.0, y: 4.0 }; + let integer_and_float = Point { x: 5, y: 4.0 }; + + println! (" + {both_integer:?} + {both_float:?} + {integer_and_float:?} + "); +} diff --git a/src/generic_types_traits_and_lifetimes/generics.md b/src/generic_types_traits_and_lifetimes/generics.md index 07cb615..b83c5b0 100644 --- a/src/generic_types_traits_and_lifetimes/generics.md +++ b/src/generic_types_traits_and_lifetimes/generics.md @@ -1,22 +1,17 @@ # 通用数据类型 -**Generic Data Types** - -这里会使用泛型,来创建诸如函数签名或结构体等的定义,随后咱们便可以将这些定义,用于许多不同的具体数据类型。首先咱们来看看,怎样运用泛型特性来定义函数、结构体、枚举及方法等。接下来就会讨论到,泛型如何影响到代码性能。 +我们使用泛型来创建函数签名或结构体等项目的定义,然后咱们可以对许多不同的具体数据类型使用他们。咱们来首先看看怎样使用泛型定义函数、结构体、枚举及方法等。然后,我们将讨论到泛型会怎样影响代码性能。 ## 函数定义方面 -**In Function Definitions** +在定义使用泛型的函数时,我们放置泛型于函数的签名中,我们通常将于其中指定参数与返回值的数据类型。这样做使我们的代码更灵活,并在防止代码重复的同时,提供更多功能给咱们函数的调用者。 +继续我们的 `largest` 函数,下面清单 10-4 显示了两个函数,均为找出切片中最大值。我们随后将合并这两个函数为使用泛型的单个函数。 -在定义用到泛型的函数时,就要把泛型放在咱们通常于其中,指明参数与返回值数据类型的函数签名中。这样做就会在阻止代码重复的同时,令到代码更为灵活,同时提供到更多功能给咱们函数的调用者。 - -继续之前的 `largest` 函数,下面清单 10-4 给出了两个均为找出某个切片中极大值的函数。这随后就要将这两个函数,合并为使用泛型特性的单个函数。 - + 文件名:`src/main.rs` - ```rust fn largest_i32(list: &[i32]) -> &i32 { let mut largest = &list[0]; @@ -46,31 +41,32 @@ fn main() { let number_list = vec! [34, 50, 25, 100, 65]; let result = largest_i32(&number_list); - println! ("极大数为 {}", result); + println! ("最大数为 {result}"); let char_list = vec! ['y', 'm', 'a', 'q']; let result = largest_char(&char_list); - println! ("极大字符为 {}", result); + println! ("最大字符为 {result}"); } ``` -*清单 10-4:两个只是名字与签名中类型不同的函数* +**清单 10-4**:仅在名字和签名类型上不同的两个函数 -其中的 `largest_i32` 函数,即为在清单 10-3 中所提取出的那个,找出某个切片中最大的 `i32` 函数。而这里的 `largest_char` 函数则是找出某个切片中的极大 `char`。由于这两个函数体有着同样代码,因此这里就要通过在单个函数中,引入泛型参数来消除重复。 +`largest_i32` 函数是我们在 [清单 10-3](../Ch10_Generic_Types_Traits_and_Lifetimes.md#listing_10-3) 中提取的函数,会找出切片中最大的 `i32` 函数。`largest_char` 函数会找出切片中的最大 `char`。两个函数体有着同样的代码,因此让我们通过在单个函数中引入泛型参数来消除重复。 -为将新单一函数中的类型参数化,咱们需要给类型参数命名,就如同咱们对某个函数的那些实参(值参数),the value parameters,所做的那样。可将任意标识符,用作类型参数名字。不过咱们将使用 `T`,这是因为根据约定,Rust 中的参数名字都是简短的,通常只有一个字母,还因为 Rust 的类型命名约定为驼峰式大小写命名规则(CamelCase)。而 `T` 作为 “type” 的简写,其便是大多数 Rust 程序员的默认选择了。 +为了参数化新的单个函数中的类型,咱们需要命名类型参数,就像我们对函数的值参数,the value parameters,所做的那样。咱们可以使用任何标识符作为类型参数的名字。但咱们将使用 `T`,因为根据约定,Rust 中的类型参数名字要短,通常只有一个字母,并且 Rust 的类型命名约定,type-naming convention,为驼峰式大小写命名规则,UpperCamelCase。`T` 为 *type* 的缩写,便是大多数 Rust 程序员的默认选择。 -当咱们要在函数体中,用到某个参数时,咱们必须在函数签名中声明出这个参数,如此编译器便知道那个名字表示什么。与此类似,当咱们要在函数签名中,用到某个类型参数名字时,在使用该类型参数之前,咱们必须声明出这个类型参数。要定义这个泛型的 `largest` 函数,就要把类型名字声明,放在尖括号(`<>`)里,于函数名字与参数列表之间,如下所示: +当我们在函数体中使用参数时,我们必须在签名中声明出参数名字,以便编译器知道该名字表示什么。同样,当咱们在函数签名中使用类型参数名字时,我们必须在使用他之前声明出类型参数名字。为了定义通用的 `largest` 函数,我们就要放置类型名字声明于函数名字与参数列表之间的尖括号,`<>` 内,如下所示: ```rust fn largest(list: &) -> &T { ``` -咱们把这个定义读作:函数 `largest` 对某个类型 `T` 通用(the function `largest` is generic over some type `T`)。该函数有着一个名为 `list` 的参数,其为类型 `T` 值切片。`largest` 函数将返回一个到同样类型 `T` 值的引用。 +我们把这个定义读作:“函数 `largest` 对某一类型 `T` 通用,the function `largest` is generic over some type `T`”。这个函数有着一个名为 `list` 的参数,其为类型 `T` 的值的切片。`largest` 函数将返回一个对同一类型 `T` 的值的引用。 -下面清单 10-5 给出了这个在其签名中用到通用数据类型的合并 `largest` 函数的定义。这个清单还展示了咱们可以怎样使用 `i32` 值切片,或 `char` 值切片调用该函数。请注意此代码尚不会编译,但咱们将在本章后面修复他。 +下面清单 10-5 显示了在其签名中使用通用数据类型合并后的 `largest` 函数的定义。这个清单还展示了咱们可以怎样以一个 `i32` 的值或 `char` 的值的切片调用该函数。请注意这段代码尚不会编译。 + 文件名:`src/main.rs` ```rust @@ -90,22 +86,22 @@ fn main() { let number_list = vec! [34, 50, 25, 100, 65]; let result = largest(&number_list); - println! ("极大数为 {}", result); + println! ("最大数为 {result}"); let char_list = vec! ['y', 'm', 'a', 'q']; let result = largest(&char_list); - println! ("极大字符为 {}", result); + println! ("最大字符为 {result}"); } ``` -*清单 10-5:使用泛型参数的 `largest` 函数;此代码尚不会编译* +**清单 10-5**:使用泛型参数的 `largest` 函数;这段代码尚不编译 -现在编译此代码,将得到如下错误信息: +当我们现在编译这段代码,我们将得到下面这个报错: ```console -$ cargo run lennyp@vm-manjaro - Compiling generics_demo v0.1.0 (/home/lennyp/rust-lang/generics_demo) +$ cargo run + Compiling generic_func v0.1.0 (/home/hector/rust-lang-zh_CN/projects/generic_func) error[E0369]: binary operation `>` cannot be applied to type `&T` --> src/main.rs:5:17 | @@ -114,25 +110,23 @@ error[E0369]: binary operation `>` cannot be applied to type `&T` | | | &T | -help: consider restricting type parameter `T` +help: consider restricting type parameter `T` with trait `PartialOrd` | 1 | fn largest(list: &[T]) -> &T { | ++++++++++++++++++++++ For more information about this error, try `rustc --explain E0369`. -error: could not compile `generics_demo` due to previous error +error: could not compile `generic_func` (bin "generic_func") due to 1 previous error ``` -帮助文本消息提到 `std::cmp::PartialOrd`,其是个 *特质(trait)*,而咱们在下一小节就会讲到特质。至于现在,明白这个报错指出了,`largest` 函数体不会对所有 `T` 可能的类型工作就行。由于咱们是要在该函数体中,比较两个类型 `T` 的值,那么咱们就只能使用值可被排序的类型。为能进行比较,标准库便有这个咱们可在类型上应用的 `std::cmp::PartialOrd` 特质(请参阅附录 C 了解该特质的更多信息)。按照该帮助信息的建议,咱们就要把对 `T` 有效的类型,限制为仅那些实现了 `PartialOrd` 的类型,而由于标准库在 `i32` 与 `char` 上,均实现了 `PartialOrd` 特质,那么这个示例就会编译了。 +帮助文本提到了 `std::cmp::PartialOrd`,其是个特质,而我们即将在下一小节中讨论特质。现在只需知道,这个报错指出 `largest` 的主体将不工作于 `T` 可能的所有可能类型。因为我们打算在函数主体中比较类型 `T` 的值,所以我们只能使用值可以排序的类型。为了支持比较操作,标准库提供了 `std::cmp::PartialOrd` 特质,咱们可以对类型实现他(请参阅 [附录 C](../appendix/derivable_traits.md#用于排序比较的-partialord-与-ord) 了解有关这一特质的更多信息)。要修复清单 10-5,我们可以按照帮助文本的建议,限制 `T` 的有效类型为仅实现 `PartialOrd` 的类型。该清单随后将编译,因为标准库在 `i32` 与 `char` 上均实现了 `PartialOrd`。 ## 结构体定义方面 -**In Struct Definitions** - - -咱们也可使用这种 `<>` 语法,将结构体定义为在其一个或多个字段中使用泛型参数。清单 10-6 定义了一个 `Point` 的结构体,来保存任意类型的 `x` 与 `y` 坐标值。 +我们也可以使用 `<>` 语法,定义结构体为在一个或多个字段中使用泛型参数。下面清单 10-6 定义了一个 `Point` 结构体来保存任意类型的 `x` 与 `y` 坐标值。 + 文件名:`src/main.rs` ```rust @@ -147,12 +141,13 @@ fn main() { } ``` -*清单 10-6:保存类型 `T` 的 `x` 与 `y` 值的 `Point` 结构体* +**清单 10-6**:保存类型 `T` 的 `x` 与 `y` 值的 `Point` 结构体 -在结构体定义中使用泛型特性的语法,与在函数定义中用到的类似。首先,在紧接着结构体名字之后,咱们于尖括号内部,声明了类型参数的名字。随后咱们在原本指明具体类型的结构体定义中,用到了那个泛型。 +在结构体定义中使用泛型的语法与在函数定义中用到的类似。首先,我们在紧接着结构体名字后的尖括号内声明类型参数的名字。然后,咱们在结构体定义中,原本指定具体类型之处使用泛型类型。 -请注意由于咱们只使用了一个泛型来定义 `Point`,那么这个定义就是说,`Point` 结构体对某些类型 `T` 通用,且不论那种类型为何,字段 `x` 与 `y` *均为* 那同一类型。当咱们要创建有着不同类型值的某个 `Point` 时,如下面清单 10-7 中,那么咱们的代码就不会编译。 +请注意,由于咱们仅使用了一种泛型类型来定义 `Point`,所以这一定义表明,`Point` 结构体对某一类型 `T` 是通用的,并且字段 `x` 和 `y` 均为同一类型,无论该类型为何。当我们创建一个有着不同类型值的 `Point`,如下面清单 10-7 中所示,我们的代码将不编译。 + 文件名:`src/main.rs` ```rust @@ -166,13 +161,13 @@ fn main() { } ``` -*清单 10-7:由于字段 `x` 与 `y` 有着同一泛型数据类型 `T`,因此他们必须为同一类型* +**清单 10-7**:字段 `x` 与 `y` 必须是同一类型,因为他们都有着相同的通用数据类型 `T` -在此示例中,当咱们把整数值 `5` 赋值给 `x` 时,咱们就让编译器明白,这个 `Point` 实例的泛型 `T` 将是个整数。随后在咱们把 `4.0` 指定给那个已被咱们定义为与 `x` 有着同一类型的 `y` 时,咱们将得到一个下面这样的类型不匹配错误: +在这个示例中,当咱们指派整数值 `5` 给 `x` 时,咱们就让编译器知道了,这个 `Point` 实例的泛型类型 `T` 将是个整数。然后,当我们为咱们已定义其与 `x` 有着同一类型的 `y` 指定 `4.0` 时,咱们将得到下面这样的类型不匹配错误: ```console -$ cargo run lennyp@vm-manjaro - Compiling generics_demo v0.1.0 (/home/lennyp/rust-lang/generics_demo) +$ cargo run + Compiling generic_struct v0.1.0 (/home/hector/rust-lang-zh_CN/projects/generic_struct) error[E0308]: mismatched types --> src/main.rs:7:38 | @@ -180,11 +175,12 @@ error[E0308]: mismatched types | ^^^ expected integer, found floating-point number For more information about this error, try `rustc --explain E0308`. -error: could not compile `generics_demo` due to previous error +error: could not compile `generic_struct` (bin "generic_struct") due to 1 previous error ``` -要定义出其中 `x` 与 `y` 同时为泛型,又可以有着不同类型的 `Point` 结构体,咱们可使用多个泛型参数。比如,在下面清单 10-8 中,就将 `Point` 的定义,修改为了对类型 `T` 与 `U` 通用,其中 `x` 为类型 `T`,而 `y` 则是类型 `U`。 +要定义一个 `Point` 结构体,其中 `x` 与 `y` 均为泛型但可以有着不同类型,我们可以使用多个泛型类型参数。比如,在下面清单 10-8 中,我们修改 `Point` 的定义为对类型 `T` 与 `U` 泛型,其中 `x` 为类型 `T`,`y` 为类型 `U`。 + 文件名:`src/main.rs` ```rust @@ -200,17 +196,14 @@ fn main() { } ``` -*清单 10-8:对两种类型通用的 `Point`,进而 `x` 与 `y` 可以是不同类型的值* +**清单 10-8**:对两种类型泛型的 `Point`,从而 `x` 与 `y` 可以是不同类型的值 -现在上面给出的全部 `Point` 实例,便都是允许的了!咱们可在某个定义中,使用咱们想要泛型参数个数,不过用多了就会令到代码难于阅读。若发现代码中需要很多泛型,那就可能表示咱们的代码,需要重新组织架构为更小的片段了。 +现在展示的所有 `Point` 实例都是允许的!咱们可在定义中使用任意数量的泛型类型参数,但使用过多会使咱们的代码难于阅读。当咱们发现代码中需要大量泛型时,则可能表明咱们的代码需要重新组织为一些更小的部分。 ## 枚举定义方面 -**In Enum Definitions** - - -如同咱们在结构体下所做的那样,咱们可定义出在其变种中,保存一些通用数据类型的枚举。咱们来换个角度看看,咱们在第 6 章中曾使用过的,标准库所提供的 `Option`: +正如我们对结构体所做的那样,咱们可以定义枚举为他们的变种中保存通用数据类型。咱们再来看看标准库提供的 `Option` 枚举,咱们曾在第 6 章中使用过他: ```rust enum Option { @@ -219,9 +212,9 @@ enum Option { } ``` -对咱们来说,这个定义现在应有着更多意涵了。可以看到,`Option` 枚举对类型 `T` 是通用的,并有着两个变种:保存着一个类型 `T` 值的 `Some`,与一个不保存任何值的 `None` 变种。经由使用这个 `Option` 枚举,咱们便可表达出可选值,an optional value,的抽象概念,而由于 `Option` 是通用的,因此咱们就可以在无关乎该可选值为何种类型下,用到这个抽象。 +这个定义现在对咱们来说应该更有意义了。正如咱们所见,`Option` 枚举对类型 `T` 是通用的,并有着两个变种:`Some`,保存着类型 `T` 的一个值,以及 `None`,不保存任何值。通过使用 `Option` 枚举,咱们可以表达可选值的抽象概念,the abstract concept of an optional value,而由于 `Option` 是泛型的,所以无论可选值是何种类型,咱们都可以使用这种抽象。 -枚举也可以使用多个泛型。在第 9 章中用到的 `Result` 枚举定义,就是一个示例: +枚举也可以使用多个泛型类型。我们曾在第 9 章中用到的 `Result` 枚举的定义就是一个示例: ```rust enum Result { @@ -230,51 +223,48 @@ enum Result { } ``` -`Result` 枚举对 `T` 和 `E` 两种类型通用,并有着两个变种:保存了一个类型 `T` 值的 `Ok`,与保存了一个类型 `E` 值的 `Err`。这个定义使得在某个操作可能成功(便返回某种类型 `T` 的一个值),或失败(便返回一个某种类型 `E` 的值)的地方,使用 `Result` 枚举方便起来。事实上,这正是咱们在清单 9-3 中,打开某个文件时所用到的,在文件被成功打开时,其中的 `T` 就以 `std::fs::File` 给填上了,而当打开那个文件时,若存在某些问题,那么其中的 `E` 就会被 `std::io::Error` 填充。 +`Result` 枚举对 `T` 和 `E` 两种类型通用,并有着两个变种:`Ok`,保存类型 `T` 的值,以及 `Err`,保存类型 `E` 的值。这一定义使得在我们有个可能成功(返回某种类型 `T` 的值)或失败(返回某种类型 `E` 的值)的任何地方,使用 `Result` 枚举都很方便。事实上,这就是我们在 [清单 9-3](../error_handling/result.md#listing_9-3) 中用于打开文件的,其中当文件成功打开时, `T` 被填充以 `std::fs::File`,而当打开文件存在问题时,`E` 就被填充以 `std::io::Error`。 -当咱们认识到咱们的代码中,有着仅在其所保存值类型方面有区别的多个结构体或枚举的情况时,咱们就可以通过使用泛型避免代码重复。 +当咱们发现咱们的代码中,多个结构体或枚举仅在他们保存的值的类型方面不同的情况时,咱们可通过使用泛型类型来避免代码重复。 ## 方法定义方面 -**In Method Definitions** - - -咱们可以在结构体与枚举上实现方法(正如在第 5 章中咱们所做的),并也可以在他们定义中使用泛型。下面清单 10-9 展示了于其上实现了名为 `x` 方法的,咱们曾在清单 10-6 中定义的 `Point` 结构体。 +我们可以在结构体及枚举上实现方法(正如我们在 [第 5 章中](../structs/method_syntax.md) 咱们所做的那样,*译注:及 [第 6 章](../enums_and_pattern_matching/defining_an_enum.md)*),并也可以在他们定义中使用泛型类型。下面清单 10-9 展示了我们在 [清单 10-6](#listing_10-6) 中定义的 `Point` 结构体,带有一个定义在其上的名为 `x` 的方法。 + 文件名:`src/main.rs` ```rust -struct Point { +struct Point { x: T, - y: U, + y: T, } -impl Point { +impl Point { fn x(&self) -> &T { &self.x } - - fn y(&self) -> &U { - &self.y - } } fn main() { let p = Point { x: 5, y: 10 }; - println! ("{}, {}", p.x(), p.y()); + println!("p.x = {}", p.x()); } ``` -*清单 10-9:在 `Point` 结构体上,实现将返回到类型 `T` 的 `x` 字段的引用的一个名为 `x` 的方法* +**清单 10-9**:在 `Point` 结构体上实现一个名为 `x` 的方法,将返回对类型 `T` 的 `x` 字段的引用 -这里已在 `Point` 上,定义了名为 `x` 的、返回到字段 `x` 中数据引用的一个方法。经由在 `impl` 后,将 `T` 声明为泛型,Rust 就可以识别出,`Point` 中尖括号(`<>`) 里的类型是个泛型而非具体类型。对于这个泛型参数,咱们可以选择不同于前面结构体定义中,所声明的泛型参数名字,但使用同一个名字是依照惯例的。在声明了泛型的 `impl` 里编写的方法,不论泛型最终将以何种具体类型所代替,这些方法都将定义在该类型的所有实例上。 +在这里,我们已在 `Point` 上定义了个名为 `x` 的方法,返回到字段 `x` 中的数据的引用。 -当咱们在类型上定义方法时,咱们还可以在泛型上指定约束条件。比如,只在 `Point` 的实例,而非任意泛型的 `Point` 实例上实现方法。在下面清单 10-10 中,咱们使用了具体类型 `f32`,意味着在 `impl` 之后咱们没有声明任何类型。 +请注意,我们必须在 `imple` 之后声明 `T`,以便我们可以使用 `T` 来指定我们正在实现类型 `Point` 上的方法。通过在 `impl` 后声明 `T` 为泛型类型,Rust 就可以识别 `Point` 中尖括号里的类型是泛型类型而非具体类型。我们可以为这个泛型参数选择一个不同的泛型参数名字,相比在结构体定义中声明的泛型参数名字,但使用同一个名字是惯例。当咱们在声明了泛型类型的 `impl` 内编写某个方法时,那么该方法将定义在这一类型的任何实例上,无论最终替换泛型类型的何种具体类型。 + +在定义泛型类型上的方法时,我们还可以指定泛型类型上的约束。例如,我们可以仅对 `Point` 的实例实现方法,而非对有着任意泛型类型的 `Point` 实例。在下面清单 10-10 中,我们使用具体类型 `f32`,这意味着我们未在 `impl` 之后声明任何类型。 + 文件名:`src/main.rs` ```rust @@ -285,11 +275,11 @@ impl Point { } ``` -*清单 10-10:只适用于有着特定具体类型泛型参数 `` 的结构体的一个 `impl` 代码块* +**清单 10-10**:一个 `impl` 代码块,仅适用于有着针对泛型类型参数 `` 的特定具体类型的结构体 -此代码表示类型 `Option` 将有一个 `distance_from_origin` 方法;其中 `T, U` 不是 `f32` 的其他 `Option` 实例,就不会被定义这个方法。该方法度量了咱们的点与坐标 `(0.0, 0.0)` 处点的距离,并使用了只对浮点数类型可行的数学运算。 +这段代码表示类型 `Option` 将有着 `distance_from_origin` 方法;而其中 `T` 不是 `f32` 的其他 `Option` 实例将不会被定义这个方法。该方法测量我们的点距坐标 `(0.0, 0.0)` 处点的有多远,并使用了仅对浮点类型可用的数学运算。 -结构体定义中的泛型参数,并不总与咱们在同一结构体方法签名中,所使用的那些泛型参数相同。为让示例更明确,下面清单 10-11 对 `Point` 结构体,使用了泛型 `T` 与 `U`,而对 `mixup` 方法签名则使用了 `X` `Y`。 +结构体定义中的泛型类型参数,并不总与咱们在同一结构体的方法签名中使用的泛型类型参数相同。为让示例更明确,下面清单 10-11 对 `Point` 结构体,使用了泛型 `T` 与 `U`,而对 `mixup` 方法签名则使用了 `X` `Y`。 这个方法使用来自 `self` `Point` 的 `x` 值(类型为 `T`),与来自传入的那个 `Point` 值的 `y` (类型为 `Y`),创建出一个新的 `Point`。 文件名:`src/main.rs`