63 lines
2.1 KiB
Rust
Executable File
63 lines
2.1 KiB
Rust
Executable File
/// 实现一个自定义的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");
|
||
}
|
||
}
|