/// 实现一个自定义的box类型,效果和Box类似, /// 目的是为了理解Deref的意义 struct MyBox(T); impl MyBox { pub fn new(item: T) -> MyBox { MyBox(item) } } use std::ops::{Deref, DerefMut}; /// 手动给MyBox实现一个defref trait impl Deref for MyBox { type Target = T; // 实现解引用,返回MyBox里面包含的数据的引用 // 这样当使用*号时候就可以获得MyBox的数据了 fn deref(&self) -> &Self::Target { &self.0 } } pub fn learn() { let x = 5; let y = MyBox::new(6); println!("X: {}, Y:{}", x, *y); // 当MyBox实现了Deref trait的时候*y即可正确通过编译。 //Rust会自动的尝试调用Defref来获得引用,看是否可以满足函数的参数要求 //这里我们使用的是MyBox类型的引用,但是print_str需要的是字符串切片, //但是通过Deref 我们可以将&Mybox变为&String,而String也实现了Defref,所以又可以变为&str,这时候就满了函数参数的要求 print_str(&MyBox::new(String::from("this is a str"))); //这种隐式的转化可以使得我们代码的可读性更好 //如果没有的话只能这样子 let temp = MyBox::new(String::from("this is a str")); //先通过*temp进行deref,获得String,在通过[...]获得字符串切片 print_str(&(*temp)[..]); //创建一个可变引用并修改其值,这需要MyBox添加DerefMut trait的支持 let mut vnum = MyBox::new(4); *vnum += 1; //drop(vnum); // 主动调用析构函数 println!("num = {}", *vnum); } fn print_str(s: &str) { println!("{}", s); } // 引用的转化会需要满足:当实现的 T的deref trait时 target 是U时, // 1. 可以实现T的可变引用转化为U的可变或者不可变引用 // 2. 可以实现T的不可变引用转化为U的不可变引用 impl DerefMut for MyBox { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } impl Drop for MyBox { fn drop(&mut self) { println!("release a MayBox obj"); } }