类型T实现AsRef trait后,其引用类型&T是否可复用该实现?
类型T实现AsRef trait后,其引用类型&T是否可复用该实现?
嘿,这个问题问得可太在点子上了——答案是必须可以!而且这完全不用你额外写一行代码,Rust标准库早就把这个便利给咱们安排得明明白白~
当你为某个类型T实现了AsRef<U>之后,Rust会自动为所有生命周期的引用类型&'a T也实现AsRef<U>。换句话说,只要T能通过as_ref()转成&U,那&T也能直接调用as_ref()拿到&U,完全复用T的AsRef实现逻辑。
就拿你给出的代码片段举例子,PathBuf本身已经实现了AsRef<Path>,那你不仅能把PathBuf的所有权直接传给foo3,还能传&PathBuf——后者根本不需要你再给&PathBuf手动写AsRef实现,直接用PathBuf的就行。甚至像String这种实现了AsRef<Path>的类型,你传&String给foo3也能正常运行,完美适配。
咱们把代码补全验证下:
use std::path::{Path, PathBuf}; fn foo1(path: &Path) { println!("{}", path.display()); } fn foo2(path: &PathBuf) { println!("{}", path.display()); } fn foo3<P: AsRef<Path>>(path: P) { println!("{}", path.as_ref().display()); } fn main() { let path_buf = PathBuf::from("/tmp/test.txt"); // 传所有权的PathBuf,正常运行 foo3(path_buf); let path_buf2 = PathBuf::from("/tmp/another.txt"); // 传&PathBuf,复用PathBuf的AsRef实现,照样跑 foo3(&path_buf2); let path_str = "/tmp/string_path.txt".to_string(); // 传&String,复用String的AsRef<Path>实现,完全没问题 foo3(&path_str); }
这种设计的好处也很直白:让要求AsRef的API兼容性拉满,不管你手里攥着的是类型的所有权,还是引用,都能无缝塞进去,不用写一堆重复的适配代码,简直是咱们这些想少写代码开发者的福音~
本质上这是Rust标准库的一种“通用覆盖实现”——针对所有满足T: AsRef<U>的类型,自动为它们的引用类型生成AsRef实现,省得咱们手动造轮子。
内容来源于stack exchange
相关产品推荐
相关产品推荐

