rust_learn/p15.smart_point/boxt/src/SmartPoint/my_box.rs

63 lines
2.1 KiB
Rust
Raw Normal View History

2024-06-08 15:01:12 +08:00
/// 实现一个自定义的box类型效果和Box<T>类似,
/// 目的是为了理解Deref的意义
struct MyBox<T>(T);
impl<T> MyBox<T> {
pub fn new(item: T) -> MyBox<T> {
MyBox(item)
}
}
use std::ops::{Deref, DerefMut};
/// 手动给MyBox实现一个defref trait
impl<T> Deref for MyBox<T> {
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<T> DerefMut for MyBox<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<T> Drop for MyBox<T> {
fn drop(&mut self) {
println!("release a MayBox obj");
}
}