From d5476ba954bf2e62aa3a85e1e4fed1b933b457e7 Mon Sep 17 00:00:00 2001 From: Jesse <35264598+JesseAtSZ@users.noreply.github.com> Date: Fri, 14 Jan 2022 10:04:15 +0800 Subject: [PATCH] Update trait.md --- book/contents/basic/trait/trait.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/book/contents/basic/trait/trait.md b/book/contents/basic/trait/trait.md index 92937a9d..13db556e 100644 --- a/book/contents/basic/trait/trait.md +++ b/book/contents/basic/trait/trait.md @@ -1,9 +1,9 @@ # 特征Trait -如果我们想定义一个文件系统,那么把这个文件系统跟底层存储解耦是很重要的。文件操作主要包含三个:`open`、`write`、`read`,这些操作可以发生在硬盘,也可以发生在缓存,可以通过网络也可以通过(我实在编不下去了,大家来帮帮我)。总之如果你要为每一种情况都单独实现一套代码,那这种实现将过于繁杂,而且也没那个必要。 +如果我们想定义一个文件系统,那么把该系统跟底层存储解耦是很重要的。文件操作主要包含三个:`open`、`write`、`read`,这些操作可以发生在硬盘,也可以发生在缓存,可以通过网络也可以通过(我实在编不下去了,大家来帮帮我)。总之如果你要为每一种情况都单独实现一套代码,那这种实现将过于繁杂,而且也没那个必要。 要解决上述问题,需要把这些行为抽象出来,就要使用Rust中的特征 `trait` 概念。可能你是第一次听说这个名词,但是不要怕,如果学过其他语言,那么大概率你听说过接口,没错,特征很类似接口。 -在之前的代码中,我们也多次见过特征的使用,例如 `#[derive(Debug)]`,它在我们定义的类型(struct)上自动派生 `Debug` 特征,接着可以使用 `println!("{:?}",x)` 打印我们定义的类型;再例如: +在之前的代码中,我们也多次见过特征的使用,例如 `#[derive(Debug)]`,它在我们定义的类型(struct)上自动派生 `Debug` 特征,接着可以使用 `println!("{:?}",x)` 打印这个类型;再例如: ```rust fn add>(a:T, b:T) -> T { a + b @@ -23,9 +23,9 @@ pub trait Summary { } ``` -这里使用 `trait` 关键字来声明一个特征,`Summary` 是特征名。在大括号中定义描述该特征包含的所有方法,比如这个特性中包含方法: `fn summarize(&self) -> String`。 +这里使用 `trait` 关键字来声明一个特征,`Summary` 是特征名。在大括号中定义了该特征的所有方法,在这个例子中是: `fn summarize(&self) -> String`。 -特征只定义行为看起来是什么样的,而不定义行为具体是怎么样的。因此、,我们只定义特征方法的签名,而不进行实现,因此方法签名结尾是 `;`,而不是一个 `{}`。 +特征只定义行为看起来是什么样的,而不定义行为具体是怎么样的。因此,我们只定义特征方法的签名,而不进行实现,此时方法签名结尾是 `;`,而不是一个 `{}`。 接下来,每一个实现这个特征的类型都需要具体实现该特征的相应方法,编译器也会确保任何实现 `Summary` 特征的类型都拥有与这个签名的定义完全一致的 `summarize` 方法。 @@ -80,14 +80,14 @@ fn main() { sunface发表了微博好像微博没Tweet好用 ``` -说实话,如果特征仅仅如此,你可能会觉得花里胡哨没啥用,接下里就让你见识下 `trait` 真正的威力。 +说实话,如果特征仅仅如此,你可能会觉得花里胡哨没啥用,接下来就让你见识下 `trait` 真正的威力。 #### 特征定义与实现的位置(孤儿规则) 上面我们将 `Summary` 定义成了 `pub` 公开的。这样,如果他人想要使用我们的 `Summary` 特征,则可以引入到他们的包中,然后再进行实现。 关于特征实现与定义的位置,有一条非常重要的原则:**如果你想要为类型 `A` 实现特征 `T`,那么 `A` 或者 `T `至少有一个是在当前作用域中定义的!**。例如我们可以为上面的 `Post` 类型实现标准库中的 `Display` 特征,这是因为 `Post` 类型定义在当前的作用域中。同时,我们也可以在当前包中为 `String` 类型实现 `Summary` 特征,因为 `Summary` 定义在当前作用域中。 -但是你无法在当前作用域中,为 `String` 类型实现 `Display` 特征,因为它们俩都定义在标准库中,它俩的定义所在的位置都不在当前作用域,跟你半毛钱关系都没有,看看就行了。 +但是你无法在当前作用域中,为 `String` 类型实现 `Display` 特征,因为它们俩都定义在标准库中,其定义所在的位置都不在当前作用域,跟你半毛钱关系都没有,看看就行了。 该规则被称为**孤儿规则**,可以确保其它人编写的代码不会破坏你的代码,也确保了你不会莫名其妙就破坏了风马牛不相及的代码。