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}