rust_learn/p15.smart_point/boxt/src/SmartPoint/my_box.rs
2024-06-08 15:01:12 +08:00

63 lines
2.1 KiB
Rust
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/// 实现一个自定义的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");
}
}