From e0ad21e72b8c211aad041a01c5f6186e8ea0a168 Mon Sep 17 00:00:00 2001 From: Shi Bin <15519900807@qq.com> Date: Sun, 16 Jul 2023 19:23:05 +0800 Subject: [PATCH] =?UTF-8?q?Fix:=20=E6=B3=A8=E9=87=8A=E5=B0=91=E4=BA=86?= =?UTF-8?q?=E7=AC=A6=E5=8F=B7=E2=80=9C::=E2=80=9D=EF=BC=9Bself=20->=20Self?= =?UTF-8?q?;=20=E5=B0=86=E5=88=B0=20->=20=E8=AE=B2=E5=88=B0=20(#29)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- md/ch11.md | 8 ++++---- src/ch11.tex | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/md/ch11.md b/md/ch11.md index 9c9e9d1..09ffcd2 100644 --- a/md/ch11.md +++ b/md/ch11.md @@ -47,7 +47,7 @@ assert_eq!(bytes, b"hello world\n"); ``` -这一章首先展示trait怎么使用、怎么工作、怎么定义自己的trait。但trait的用途比我们目前提到的更多。我们将使用它们给现有类型添加扩展的方法,甚至像`str`和`bool`这种内建类型也可以。我们将会解释为什么给一个类型添加trait不会消耗多余的内存,以及如何在没有虚方法开销的情况下使用trait。我们将看到一些Rust提供的用于操作符重载和其他特性的语言内建的trait。我们还将介绍`Self`类型、关联函数、关联类型。Rust从Haskell中提取了这三个特性,它们可以优雅地解决其他语言中需要通过变通的方法或者hack才能解决的问题。 +这一章首先展示trait怎么使用、怎么工作、怎么定义自己的trait。但trait的用途比我们目前提到的更多。我们将使用它们给现有类型添加扩展的方法,甚至像`str`和`bool`这种内建类型也可以。我们将会解释为什么给一个类型添加trait不会消耗多余的内存,以及如何在没有虚方法开销的情况下使用trait。我们将看到一些Rust提供的用于操作符重载和其他特性的语言内建的trait。我们还将介绍`Self`类型、关联函数、关联类型。Rust从Haskell中提取了这三个特性,它们可以优雅地解决其他语言中需要通过变通的方法或者hack才能解决的问题。 *泛型* 是Rust中另一种形式的多态。类似于C++的模板,一个泛型函数或类型可以用于多种不同的类型: ```Rust @@ -176,7 +176,7 @@ C++也有这种运行时的类型信息。它被称为 *虚表* 或者 *vtable* 类型`W`到底是什么取决于泛型函数如何被调用: ```Rust say_hello(&mut local_file)?; // 调用say_hello:: - say_hello(&mut bytes)?; // 调用say_hello> + say_hello(&mut bytes)?; // 调用say_hello::> ``` 当你把`&mut local_file`传递给泛型的`say_hello()`函数时,你实际是在调用`say_hello::()`。Rust会为这个函数生成机器码,机器码里还会调用`File::write_all()`和`File::flush()`。当你传递`&mut bytes`时,你实际是在调用`say_hello::>()`。Rust会为这个版本的函数生成单独的机器码,然后调用相应的`Vec`的方法。在这两种情况下,Rust都从参数的类型推导出类型`W`,这个过程被称为 *单态化(monomorphization)* ,编译器会自动进行处理。 @@ -334,7 +334,7 @@ trait对象就是解决方案: 相比与trait对象的行为,Rust直到运行时才能知道一个trait对象指向的值到底是什么类型。因此即使你传递了一个`Sink`,虚方法的调用开销和检查错误的开销仍然不可避免。 -泛型的第二个优势是有的trait不支持trait对象。trait只支持一部分特性,例如关联函数只能使用泛型,这样就完全排除了trait对象。当我们将到这些特性时会指出它们。 +泛型的第二个优势是有的trait不支持trait对象。trait只支持一部分特性,例如关联函数只能使用泛型,这样就完全排除了trait对象。当我们讲到这些特性时会指出它们。 泛型的第三个优势是可以很容易地一次给泛型类型参数添加多个trait约束,例如我们的`top_ten`函数就要求它的参数`T`要实现`Debug + Hash + Eq`。trait对象不能这么做:Rust不支持类似`&mut (dyn Debug + Hash + Eq)`这样的类型。(你可以用本章中稍后会讲到的”子trait”来实现类似的功能,但这样有点复杂。) @@ -655,7 +655,7 @@ trait对象实际上是为最简单的trait设计的,就是那种可以用Java ```Rust trait StringSet { - fn new() -> self + fn new() -> Self where Self: Sized; fn from_slice(strings: &[&str]) -> Self diff --git a/src/ch11.tex b/src/ch11.tex index 8f10055..1e59fd7 100644 --- a/src/ch11.tex +++ b/src/ch11.tex @@ -182,7 +182,7 @@ \subsection{泛型函数和类型参数} 类型\texttt{W}到底是什么取决于泛型函数如何被调用: \begin{minted}{Rust} say_hello(&mut local_file)?; // 调用say_hello:: - say_hello(&mut bytes)?; // 调用say_hello> + say_hello(&mut bytes)?; // 调用say_hello::> \end{minted} 当你把\texttt{\&mut local\_file}传递给泛型的\texttt{say\_hello()}函数时,你实际是在调用\\ @@ -347,7 +347,7 @@ \subsection{选择哪一种}\label{WhichToUse} 相比与trait对象的行为,Rust直到运行时才能知道一个trait对象指向的值到底是什么类型。因此即使你传递了一个\texttt{Sink},虚方法的调用开销和检查错误的开销仍然不可避免。 -泛型的第二个优势是有的trait不支持trait对象。trait只支持一部分特性,例如关联函数只能使用泛型,这样就完全排除了trait对象。当我们将到这些特性时会指出它们。 +泛型的第二个优势是有的trait不支持trait对象。trait只支持一部分特性,例如关联函数只能使用泛型,这样就完全排除了trait对象。当我们讲到这些特性时会指出它们。 泛型的第三个优势是可以很容易地一次给泛型类型参数添加多个trait约束,例如我们的\texttt{top\_ten}函数就要求它的参数\texttt{T}要实现\texttt{Debug + Hash + Eq}。trait对象不能这么做:Rust不支持类似\texttt{\&mut (dyn Debug + Hash + Eq)}这样的类型。(你可以用本章中稍后会讲到的\hyperref[subtrait]{子trait}来实现类似的功能,但这样有点复杂。) @@ -666,7 +666,7 @@ \subsection{类型关联函数} \begin{minted}{Rust} trait StringSet { - fn new() -> self + fn new() -> Self where Self: Sized; fn from_slice(strings: &[&str]) -> Self