有位小伙伴发了如下一段代码, 要求帮忙解释下, 觉得好奇为什么Path::new能接受不同类型的入参.
use std::path::Path;fn main() { let str: &str = "/Users/zjl/project/1.txt"; // Path::new 接受了 字符串字面量(切片) 作为参数 let path_from_str: &Path = Path::new(str); let string: String = String::from("/Users/zjl/project/1.txt"); // Path::new 接受了 String的引用 作为参数 let path_from_string: &Path = Path::new(&string); // 获取文件名 if let Some(file_name) = path_from_str.file_name() { println!("文件名: {:?}", file_name); } // 获取文件名 if let Some(file_name) = path_from_string.file_name() { println!("文件名: {:?}", file_name); }}
其实知识点很简单: trait作为参数来接受多种不同类型的参数, 提供更灵活的参数接受方式, 并增加代码的可重用性和泛化性.
关于 trait 作为参数的教程: Trait:定义共同行为 - Rust 程序设计语言 简体中文版、Traits: Defining Shared Behavior - The Rust Programming Language
Path::new的源代码如下:
pub fn new<S: AsRef<OsStr> + ?Sized>(s: &S) -> &Path { unsafe { &*(s.as_ref() as *const OsStr as *const Path) }}
参数类型S要求是实现了 AsRef<OsStr> trait.
AsRef 字面含义是"作为引用", 理解为将一种类型的引用转化为另一种类型的引用.
pub trait AsRef<T>where T: ?Sized,{ // Required method fn as_ref(&self) -> &T;}
通过以上Trait源码也是这个含义(将一种类型的引用转化为另一种类型的引用)
new的入参要求只要是实现了 AsRef<OsStr> trait的类型其实都可以.
查看标准库文库, 不难发现:
impl AsRef<OsStr> for strimpl AsRef<OsStr> for OsStrimpl AsRef<OsStr> for OsStringimpl AsRef<OsStr> for Components<'_>impl AsRef<OsStr> for std::path::Iter<'_>impl AsRef<OsStr> for Pathimpl AsRef<OsStr> for PathBufimpl AsRef<OsStr> for String
以上类型都实现了 AsRef trait, 不光是str、String能作为参数, 其实还有 OsStr、OsString、Components<'>、std::path::Iter<'>、Path、PathBuf 都可以作为参数.
希望对大家有用, 多多交流.
版权声明:内容来源于互联网和用户投稿 如有侵权请联系删除