【Rust中级教程】1.17. 孤儿规则与连贯性(一致性):泛实现(Blanket Implementation)、覆盖实现(Covered Implementation)

发布时间:2026/7/24 20:42:34

【Rust中级教程】1.17. 孤儿规则与连贯性(一致性):泛实现(Blanket Implementation)、覆盖实现(Covered Implementation) 1.17 孤儿规则与连贯性(一致性)泛实现(Blanket Implementation)、覆盖实现(Covered Implementation)1.17.1. 连贯性(一致性)属性连贯性(或者叫一致性)是指对于给定的类型和方法只会有一个正确的选择用于该方法对该类型的实现。孤儿规则(orphan rule)指的是只要trait或者类型在本地的crate那就可以为该类型实现该trait。比如说:- 你定义在本地的类型可以实现Debugtrait- 可以为bool类型实现你定义在本地的trait- 不能为bool类型实现Debugtrait因为这两者都不是定义在本地的这个孤儿规则也有例外我们下文再讲。1.17.2. 泛实现(Blanket Implementation)泛实现(Blanket Implementation)又叫通用实现它指的是Rust允许为所有符合某个trait约束的类型提供默认实现。它的模版是implT MyTrait for T where T:它的意思是为所有实现了某个trait的类型实现MyTrait。例如implT: Display ToString for T {}这句话的意思是为所有实现了Displaytrait的类型实现了ToStringtrait。这个例子的写法还不是模版的写法换成模版的写法就是implT ToString for T where T: Display {}需要注意的是只有定义trait的crate允许使用泛实现。添加泛实现到现有trait属于破坏性变化。1.17.3. 基础类型有些类型太过于基础了需要允许任何人在它们上实现trait(即使违反孤儿规则)。这些类型被标记为#[fundamental]目前包括T、mut T、BoxT、PinP。- 一点补充PinP的主要作用是确保某个值无法被移动即防止Rust代码调用std::mem::replace、std::mem::swap或者std::mem::take之类的操作导致值的物理地址发生变化- 处于孤儿原则的目的实际上在孤儿规则检查之前它们会被抹除注意对于基础类型使用泛实现也被认为是破坏性变化。1.17.4. 覆盖实现(Covered Implementation)有时候需要为外部类型实现外部trait这就叫覆盖实现(Covered Implementation)。这样写使用到了孤儿规则制定的一个狭窄的豁免允许在非常特定的情况下为外来类型实现外部trait。注意覆盖实现既可以指Covered Implementation也可以指Override Implementation又叫覆写实现这里指的是Covered Implementation。覆写实现指的是当结构体实现 trait并提供自己的方法时可以覆写Override默认实现。这种写法的模版是implP1..Pn ForeignTriatT1..Tn for T0P1..Pn和T1..T0指的是若干个参数这种写法只在以下条件被允许-T1..Tn里至少有一个是本地类型- 没有T(T是指泛型类型P1..Pn中的一个)在第一个这样的本地类型之前- 泛型类型参数P允许出现在T0..Ti只要它们被某种中间(intermediate)类型所包裹- 如果T作为其他类型(例如VecT)的类型参数出现那就说明T被包裹了-T只作为本身或者位于基础类型后(例如T)就不是包裹举个简单的例子比如说impl FromMyType for Veci32需要为外部的Veci32这个类型来实现FromMyType这个trait再举一些复杂的例子你可以对照着规则来理解实现是否可行implT FromT for MyTypeOKimplT FromT for MyTypeTOKimplT FromMyType for VecTOKimplT ForeignTraitMyType, T for VecTOK--------------------------------------------------------implT ForeignTrait for TNot OKimplT FromT for TNot OKimplT FromVecT for TNot OKimplT FromMyTypeT for TNot OKimplT FromT for VecTNot OKimplT ForeignTraitT, MyType for VecTNot OK判断覆盖实现是否是破坏性变化需要结合实际情况- 为现有trait添加新的实现且至少包含一个新的本地类型该本地类型满足和面条件这就是非破坏性的变化- 为现有的trait添加的实现不满足上述要求就是破坏性变化注意-implT ForeignTraitMyType, T for VecT是合法的-implT ForeignTraitT, MyType for VecT是非法的

相关新闻