如何抽象对值或值本身的引用?

时间:2016-12-14 15:27:27

标签: reference rust

我有一个特性,它定义了一个可以容纳值的对象的接口。特征有一种获得当前价值的方法:

pub trait HasValue<T> {
    fn get_current_value(&self) -> &T;
}

这很好,但我意识到,根据实际的实施情况,如果T存储在字段中,有时返回引用会很方便,有时返回方便如果支持字段跨线程共享(例如),则为T的克隆。我正在努力弄清楚如何在特质中表现出来。我可以这样:

pub enum BorrowedOrOwned<'a, T: 'a> {
    Borrowed(&'a T),
    Owned(T)
}

impl<'a, T: 'a> Deref for BorrowedOrOwned<'a, T> {
    type Target = T;

    fn deref(&self) -> &T {
        use self::BorrowedOrOwned::*;

        match self {
            &Borrowed(b) => b,
            &Owned(ref o) => o,
        }
    }
}

并更改get_current_value()以返回BorrowedOrOwned<T>,但我不确定这是不是惯用的。 BorrowedOrOwned<T>让我想起了Cow<T>,但是因为Cow的目的是写时复制而且我将丢弃任何写入,这似乎是语义上的错误。

Cow<T>是引用引用或拥有值的正确方法吗?有没有比BorrowedOrOwned<T>更好的方式?

1 个答案:

答案 0 :(得分:7)

我建议您使用Cow,因为BorrowedOrOwnedCow没有区别,只是它的便捷方法较少。获取BorrowedOrOwned对象的任何人都可以匹配它并获得拥有的值或对它的可变引用。如果您想避免混淆能够获得可变引用或对象本身,下面的解决方案也适用。

对于您的使用案例,我只是坚持&T,因为没有理由让API更复杂。如果用户想要usize,当Tusize时,他们只需取消引用该引用。

如果您希望用户以自己的方式实际处理它,那么拥有的对象才有意义。即使在那时,Cow也意味着抽象你通过所有权传递的大/重物体,目的是不要求任何人clone。您的用例恰恰相反,您希望按所有权传递小对象,以防止用户需要复制小对象,而是复制它。