1.17.1. 一致性
一致性意味着对于给定的类型和方法,该方法在该类型上的实现只有一种正确的选择。
孤儿规则意味着只要 trait 或类型中任意一方位于本地 crate,你就可以为该类型实现该 trait。 例如:
- 本地定义的类型可以实现
Debugtrait - 你可以为
bool实现本地定义的 trait - 你不能为
bool实现Debug,因为双方都不在本地
孤儿规则存在例外,我们将在下文讨论。
1.17.2. 毯式实现
毯式实现(也称通用实现)是指 Rust 允许为满足 trait bound 的所有类型提供默认实现。
其模板为:
impl<T> MyTrait for T where T: ...
Enter fullscreen mode Exit fullscreen mode
这意味着为实现某个 trait 的所有类型实现 MyTrait。
例如:
impl<T: Display> ToString for T {}
Enter fullscreen mode Exit fullscreen mode
这意味着为实现 Display 的所有类型实现 ToString。
此示例尚未使用模板形式书写。使用模板形式应为:
impl<T> ToString for T where T: Display {}
Enter fullscreen mode Exit fullscreen mode
注意:只有定义该 trait 的 crate 才允许使用毯式实现。向现有 trait 添加毯式实现属于破坏性变更。
1.17.3. 基础类型
某些类型非常基础,我们需要允许任何人对其实现 trait,即使这会违反孤儿规则。这些类型被标记为 #[fundamental],目前包括 &T、&mut T、Box<T> 和 Pin<P>。
- 额外说明:
Pin<P>的主要目的是确保值无法被移动,即阻止std::mem::replace、std::mem::swap或std::mem::take等操作改变值的物理地址 - 就孤儿规则而言,这些类型在进行孤儿规则检查前会被视作已擦除
注意:对基础类型使用毯式实现同样被视为破坏性变更。
1.17.4. 覆盖实现
有时你需要为外部类型实现外部 trait,这被称为覆盖实现。它利用了孤儿规则的一个狭窄例外:允许在非常特定的情况下为外部类型实现外部 trait。
注意:覆盖实现既可指 Covered Implementation,也可指 Override Implementation。此处指 Covered Implementation。Override Implementation 指结构体在实现 trait 时提供自己的方法,从而覆盖默认实现。
此形式的模板为:
impl<P1..=Pn> ForeignTrait<T1..=Tn> for T0
Enter fullscreen mode Exit fullscreen mode
-
P1..=Pn和T1..=T0指代若干参数
仅当满足以下全部条件时,此形式才被允许:
T1..=Tn中至少有一个是本地类型- 在第一个本地类型之前,任何
T(其中T是P1..=Pn中的泛型类型之一)都不得出现 - 泛型参数
P可以出现在T0..Ti中,只要它被某种中间类型包裹- 若
T作为另一类型的类型参数出现(如Vec<T>),则认为T被包裹 - 若
T单独出现,或仅位于基础类型(如&T)之后,则认为未被包裹
- 若
简单示例:
impl From<MyType> for Vec<i32>
Enter fullscreen mode Exit fullscreen mode
这为外部类型 Vec<i32> 实现了外部 trait From<MyType>。
以下是一些更复杂的示例,你可以使用上述规则理解它们:
| 实现 | 有效? |
|---|---|
impl<T> From<T> for MyType |
OK |
impl<T> From<T> for MyType<T> |
OK |
impl<T> From<MyType> for Vec<T> |
OK |
impl<T> ForeignTrait<MyType, T> for Vec<T> |
OK |
-------------------------------------------- |
------------ |
impl<T> ForeignTrait for T |
Not OK |
impl<T> From<T> for T |
Not OK |
impl<T> From<Vec<T>> for T |
Not OK |
impl<T> From<MyType<T>> for T |
Not OK |
impl<T> From<T> for Vec<T> |
Not OK |
impl<T> ForeignTrait<T, MyType> for Vec<T> |
Not OK |
覆盖实现是否属于破坏性变更取决于具体情况:
- 向现有 trait 添加新实现,且至少有一个新本地类型满足上述条件,则是非破坏性变更
- 为现有 trait 添加不满足上述条件的实现,则是破坏性变更
注意:
-
impl<T> ForeignTrait<MyType, T> for Vec<T>是有效的 -
impl<T> ForeignTrait<T, MyType> for Vec<T>是无效的
0 Comments
Log in to join the conversation.No comments yet. Be the first to share your thoughts.