Update trait-object.md

pull/201/head
Jesse 3 years ago committed by GitHub
parent 7a8b7dc719
commit 5e1c52347b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -287,13 +287,13 @@ fn main() {
当理解了 `self``Self` 的区别后,我们再来看看何为对象安全。 当理解了 `self``Self` 的区别后,我们再来看看何为对象安全。
## 特征对象的限制 ## 特征对象的限制
不是所有特征都能拥有特征对象,只有对象安全的特征才行。当一个特征的所有方法都有如下属性时,对象才是安全的: 不是所有特征都能拥有特征对象,只有对象安全的特征才行。当一个特征的所有方法都有如下属性时,它的对象才是安全的:
- 方法的返回类型不能是`Self` - 方法的返回类型不能是 `Self`
- 方法没有任何泛型参数 - 方法没有任何泛型参数
对象安全对于特征对象是必须的,因为一旦有了特征对象,就不再需要知道实现该特征的具体类型是什么了。如果特征方法返回具体的 `Self` 类型,但是特征对象忘记了其真正的类型,那这个 `Self` 就非常尴尬,因为没人知道它是谁了。同理对于泛型类型参数来说,当使用特征时其会放入具体的类型参数:此具体类型变成了实现该特征的类型的一部分。当使用特征对象时其具体类型被抹去了,故而无从得知放入泛型参数类型到底是什么。 对象安全对于特征对象是必须的,因为一旦有了特征对象,就不再需要知道实现该特征的具体类型是什么了。如果特征方法返回具体的 `Self` 类型,但是特征对象忘记了其真正的类型,那这个 `Self` 就非常尴尬,因为没人知道它是谁了。但是对于泛型类型参数来说,当使用特征时其会放入具体的类型参数:此具体类型变成了实现该特征的类型的一部分。当使用特征对象时其具体类型被抹去了,故而无从得知放入泛型参数类型到底是什么。
标准库中的 `Clone` 特征就不符合对象安全的要求: 标准库中的 `Clone` 特征就不符合对象安全的要求
```rust ```rust
pub trait Clone { pub trait Clone {
@ -305,7 +305,7 @@ pub trait Clone {
`String` 类型实现了 `Clone` 特征, `String` 实例上调用 `clone` 方法时会得到一个 `String` 实例。类似的,当调用 `Vec<T>` 实例的 `clone` 方法会得到一个 `Vec<T>` 实例。`clone` 的签名需要知道什么类型会代替 `Self`,因为这是它的返回值。 `String` 类型实现了 `Clone` 特征, `String` 实例上调用 `clone` 方法时会得到一个 `String` 实例。类似的,当调用 `Vec<T>` 实例的 `clone` 方法会得到一个 `Vec<T>` 实例。`clone` 的签名需要知道什么类型会代替 `Self`,因为这是它的返回值。
如果违反了对象安全的规则,编译器会提示你。例如,如果尝试使用之前的`Screen`结构体来存放实现了 `Clone`特征的类型: 如果违反了对象安全的规则,编译器会提示你。例如,如果尝试使用之前的 `Screen` 结构体来存放实现了 `Clone` 特征的类型:
```rust ```rust
pub struct Screen { pub struct Screen {

Loading…
Cancel
Save