rust 的 defer 几个使用场景
pub trait Deref {
type Target: ?Sized;
// Required method
fn deref(&self) -> &Self::Target;
}
Defer
这个 trait
有一个关联类型,defer
这个函数返回的是关联类型的引用,而不是取消引用的值,这一点可能会造成误解。
可以这样来理解:给定类型 T
, 为 T
实现 Defer
是让编译器可以把 &T
引用为 &Target
,对使用者面言,操作包装器跟操作实际被包装的类型一样,简化操作。
使用场景:隐式调用 Target
的字段或者方法
struct Point { x: f32, y: f32 }
fn main() {
let boxed: Box<Point> = Box::new(Point { x: 5, y: 10 });
println!("X: {}", boxed.x);
}
boxed
并没有 x
字段,但是能正常编译运行。 这是因为编译器首先会先查看 boxed
是否有 x
字段, 如果没有,则会检测是否实现的 Defer
,再看 <T as Defer>::Target
有没有 x
的字段。
所以 boxed.x
实际是 boxed.defer().x
,编译器可以让我们省略这个 .defer()
的调用,简化操作,像直接操作 Point
一样。
使用场景:借用操作
fn main() {
let boxed: Box<i32> = Box::new(5);
print(&boxed);
}
fn print(input: &i32) {
println!("Input: {input}");
}
这里编译器会检查 &boxed
是否是类型 &i32
,如果不是,也会检查是否实现了 Defer
,然后检查 &Target
是否是 &i32
。
所以 print(&boxed)
实际是 print(boxed.defer())
,这个 &
借用操作隐式调用了 defer()
。
使用场景:* 指针操作符
*
操作是与 &
相互的, *
是取值。
fn main() {
let boxed: Box<&str> = Box::new("hello world");
let deref_result: &str = *boxed;
}
需要注意,这个 *
改变的是 Target
的值,如:
fn main() {
let mut boxed: Box<Vec<i32>> = Box::new(vec![2, 5]);
*boxed = vec![3, 4];
// 编译过不去,类型不匹配
*boxed = Box::new(vec![3, 5]);
}
使用场景: 隐式链式调用
fn main() {
let boxed = Box::new(Box::new(Box::new("hello world")));
let v = &boxed;
println!("{v}");
}
任意类型只要实现了 Defer
,都可以被这样链式隐式调用 defer()
,编译器做了这些检测,方便我们操作,而不是显示这样 T.defer().defer()...
。