rust 通过AsRef(Path)实现一个结构体的克隆特征,该结构体包含一个指向路径的泛型引用

xvw2m8pv  于 12个月前  发布在  其他
关注(0)|答案(2)|浏览(145)

我有一个结构体,看起来像这样:

pub struct MyConfig<P>
{
    // Path to file
    pub file_path: P,
    // Other settings
    pub setting1: u8,
    // [...]
}

impl <P: AsRef<Path> + std::fmt::Debug> MyConfig<P>
{
    pub fn with_path(file_path:: P) -> Result<Self>
    {
        MyConfig
        {
            file_path,
            setting1: 1
        }
    }
}

我需要一种方法来克隆配置对象。我不能只是#[derive(Clone)],因为P trait绑定。我尝试手动实现Clone,但我找不到一种方法来创建file_path属性的通用副本/克隆。例如,为什么这不起作用:

impl <P: AsRef<Path> + std::fmt::Debug> Clone for MyConfig<P>
{
    fn clone(&self) -> Self {
        Self { file_path: Path::new(self.file_path.as_ref().file_name()),
               setting1: self.setting1.clone(),
            }
    }
}

我是Rust的新手,所以也许这是一个非常愚蠢的问题(或实现),但我真的对这个看似微不足道的问题束手无策!

cczfrluj

cczfrluj1#

AsRef<Path>的目的是让你的 * 公共函数 * 更可用,这样你就可以用&strString&PathPathBuf类型的值来调用它们。但是没有理由持有如此通用的值。如果您是新手并且不确定AsRef<Path>的开始是什么,那么这一点更加适用-在这种情况下,在公共API中接受AsRef<Path>,并立即将其转换为PathBuf

#[derive(Debug, Clone)]
pub struct MyConfig {
    // Path to file
    pub file_path: PathBuf,
    // Other settings
    pub setting1: u8,
    // [...]
}

impl MyConfig {
    pub fn with_path(file_path: impl AsRef<Path>) -> Self {
        MyConfig {
            file_path: file_path.as_ref().to_owned(),
            setting1: 1,
        }
    }
}

Playground
通过这种方式,您可以获得一个完全拥有的对象,该对象可以派生CloneDebug
高级用法备注:当您无条件地创建PathBuf时,您也可以接受file_path: impl Into<PathBuf>,并使用file_path.into()创建pathbuf。这将像AsRef<Path>一样接受类似的类型选择,但如果调用者传递的是自己拥有的StringPathBuf,则将避免重新分配。该技术用于例如。通过fs_err crate来避免不必要的分配。

jmp7cifd

jmp7cifd2#

AsRef是一个trait,用于封装对底层对象的引用的类型。例如,AsRef<Path>&PathPathBufRc<Path>Arc<Path>等实现。当你不关心一个类型是被借用的还是被拥有的时候,这是很方便的。
然而,AsRef<T>不一定是可克隆的:例如,&mut T就不是。
您可以要求您的P实现Clone,以便您的结构实现Clone,这将解决您的即时编译错误:

impl <P: AsRef<Path> + std::fmt::Debug + Clone> Clone for MyConfig<P>

但请记住,如果P是一个引用,它的克隆也将是。MyConfig的克隆将只保留引用的副本,而没有所有权。这可能是,也可能不是你想要的。由于clone()要求您返回Self-与被克隆的结构具有相同泛型参数的结构,因此您无法使用标准Clone trait来解决这个问题,并且必须使用不同的方法或trait来实现这种“深度复制”。

相关问题