study_example/smart_pointer/
deref_trait.rs

1fn pointer_to_int() {
2    let x = 5;
3    let y = &x;
4    assert_eq!(5, x);
5    // error[E0277]: can't compare `{integer}` with `&{integer}`
6    // assert_eq!(5, y);
7    let z = Box::new(x);
8    assert_eq!(5, *z);
9}
10
11struct MyBox<T>(T);
12
13impl<T> MyBox<T> {
14    fn new(x: T) -> MyBox<T> {
15        MyBox(x)
16    }
17}
18
19impl<T> std::ops::Deref for MyBox<T> {
20    // type Target = T; 语法定义了要使用的 Deref 特征的关联类型
21    // 联类型是声明泛型参数的一种稍微不同的方式
22    type Target = T;
23
24    // 如果没有 Deref 特征,编译器只能取消引用 & 引用。
25    // deref 方法使编译器能够获取实现 Deref 的任何类型的值,并调用 deref 方法来获取 & 引用它知道如何取消引用
26    fn deref(&self) -> &Self::Target {
27        // .0 访问元组结构中的第一个值
28        &self.0
29    }
30}
31
32// 参数为字符串切片
33fn hello_print(str_val: &str) {
34    println!("hello {str_val}");
35}
36
37/// 运行结果为
38/// ```txt
39/// hello Rust deref coercion
40/// hello Rust deref coercion
41/// ```
42fn my_box_test() {
43    let x = 10;
44    let y = MyBox::new(x);
45    assert_eq!(10, x);
46    // error[E0614]: type `MyBox<{integer}>` cannot be dereferenced,
47    // 解决办法:在MyBox上实现Deref Trait
48    assert_eq!(10, *y); // *y实际上等同于 *(y.deref());
49    let string_type_box = MyBox::new(String::from("Rust deref coercion"));
50    /*
51       step 1: 因为MyBox实现了Deref trait, &string_type_box 调用 deref转换为了&String
52       step 2: 因为String实现了Deref trait,Rust再次调用Deref将&String转换为了&str
53    */
54    hello_print(&string_type_box);
55    // 等同于如下 *先deref拿到字符串 &取字符串的引用 [..]获取切片
56    hello_print(&(*string_type_box)[..]);
57}
58
59pub fn deref_trait_study() {
60    pointer_to_int();
61    my_box_test();
62}