一、什么是孤儿规则
有些资料中在介绍Rust trait时,往往会带出:
Rust 有一个“孤儿规则”(orphan rule),简称OR:
“当你为某类型实现某 trait 的时候,必须要求类型或者 trait 至少有一个是在当前 crate 中定义的。你不能为第三方的类型实现第三方的 trait 。”
“在调用 trait 中定义的方法的时候,一定要记得让这个 trait 可被访问。”
不知道大家是不是都了解上面的话,在说什么? 反正不容易搞清楚。
具体地说:
(1)如果要实现外部定义的 trait 需要先将其导入作用域。
(2)不允许对外部类型实现外部 trait;
(3)可以对外部类型实现自定义的 trait;
(4)可以对自定义类型上实现外部 trait。
外部是指不是由自己,而是由外部定义的,包括标准库。
case1
let mut f = std::fs::File::open("C:/Users/rustr/Desktop/foo.txt").ok().expect("Couldn’t open foo.txt");
let buf = b"whatever"; // buf: &[u8; 8]
let result = f.write(buf);
# result.unwrap();
报错=>
error[E0599]: no method named `write` found for type `std::fs::File` in the current scope
--> src\main.rs:51:20
|
51 | let result = f.write(buf);
| ^^^^^
|
= help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope, perhaps add a `use` for it:
|
1 | use std::io::Write;
因为违反了第一条“如果要实现外部定义的 trait 需要先将其导入作用域”。
加上下面的就好了:
use std::io::Write
case2:
use std::ops::Add;
struct mydata(i32);
impl Add<i32> for mydata{
type Output =i32;
fn add (self,other:i32)->Self::Output{
(self.0) + other
}
}
fn main(){
assert_eq!(mydata(5)+6,11);
}
为什么不违反OR规则?
mydata的类型是本地的;虽然Add trait是标准库带的。=》“可以对自定义类型上实现外部 trait。”
case3: 如果加上一个新的类型
impl Add<i32> for Option<mydata>{
type Output =i32;
fn add (self,other:i32)->Self::Output{
(self.0) + other
}
}
为什么编译会违反OR?
因为Option< mydata >不是本地定义的类型。即=>“不允许对外部类型实现外部 trait;”
二、一些特例:Box、Fn、FnMut、FnOnce、Sized;与 #【fundamental】
impl Add<i32> for Box<mydata>{
type Output =i32;
fn add (self,other:i32)->Self::Output{
(self.0) + other
}
}
根据“不允许对外部类型实现外部 trait:,上面的类型Box < mydata > 也应编译通不过。但实际上,是可以的。
Rust对Box< T >开了绿灯,这个 绿灯,是rust内部在类型定义时,在Box类型时,用了特别的标识
#[fundamental]
三、为什么rust要设OR ? 有什么苦衷?
特补充。。。。。。
OR 是为了加快编译?或在指向上更加清晰?