前几天群里面有人讨论Rust的孤儿规则,我看到有些网友对Rust孤儿规则不是很了解。于是就有了本文的出现。如果对这个规则不了解,估计对trait的使用也不熟悉,总结放到结尾记住这句话就可以了,以后就不用担心使用别人的包出现孤儿规则啦!
什么是孤儿规则
Rust的孤儿规则(Orphan Rule)是Rust语言中的一项特性,它确保了类型和特征(trait)的实现的一致性和安全性。具体来说,孤儿规则规定,如果你想要为一个类型实现一个特征,那么类型或特征中至少有一个必须在当前的代码包(crate)中定义。Rust中的孤儿规则是一条规定,禁止你在trait和类型都定义在crate外部的情况下,为该类型实现该trait。这条规则有助于避免多个crate为同一类型实现同一trait时可能产生的冲突和歧义。
通过示例来解释孤儿规则
让我们通过一个例子来详细说明:
在不同crate中定义trait和类型:
1. Crate A定义了一个trait。
2. Crate B定义了一个类型。
3. Crate C尝试为Crate B中的类型实现Crate A中的trait。
CrateA项目中
// src/lib.rs
pub trait Greet {
fn greet(&self);
}
CrateB项目中
// src/lib.rs
pub struct Person {
pub name: String,
}
CrateC项目中: 实现
// src/lib.rs
extern crate trait_crate;
extern crate type_crate;
use trait_crate::Greet;
use type_crate::Person;
// 堆代码 duidaima.com
// 由于孤儿规则,这将无法编译
impl Greet for Person {
fn greet(&self) {
println!("你好,我的名字是{}", self.name);
}
}
A定义了Greet trait。B定义了Person结构体。C尝试为Person结构体实现Greet trait。孤儿规则阻止了C为Person结构体实现Greet trait,因为trait和类型都定义在C之外。
如何修改这样的错误呢?
你可以在以下情况下为类型实现trait,只要其中至少一个是定义在你的crate中的:
1. 为外部类型实现本地trait:
你可以在你的crate中定义一个新的trait,并为其外部类型实现该trait。Crate C: impl_crate
extern crate type_crate;
use type_crate::Person;
// 定义一个新的trait去实现Person,就可以使用Person这个结构体的属性了。
pub trait Farewell {
fn farewell(&self);
}
impl Farewell for Person {
fn farewell(&self) {
println!("Goodbye from {}", self.name);
}
}
为本地类型实现外部trait:你可以为在你的crate中定义的类型实现一个外部trait。和上面的反过来,在自己的包里面定一个新的结构体然后实现trait Greet。
extern crate trait_crate;
use trait_crate::Greet;
pub struct LocalPerson {
pub name: String,
}
impl Greet for LocalPerson {
fn greet(&self) {
println!("Hello, my name is {}", self.name);
}
}
总结
孤儿规则确保你只能为类型实现trait,如果其中至少一个是本地于你的crate的。这有助于防止多个crate为同一类型实现同一trait时可能产生的冲突和歧义。