我有一个特性,它定义了一个可以容纳值的对象的接口.特征有一种获取当前值的方法:
pub trait HasValue<T> {
fn get_current_value(&self) -> &T;
}
Run Code Online (Sandbox Code Playgroud)
这很好,但我意识到,根据实际的实现,有时如果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,
}
}
}
Run Code Online (Sandbox Code Playgroud)
并get_current_value()改为返回,BorrowedOrOwned<T>但我不确定这是不是惯用的.BorrowedOrOwned<T>有点让我想起Cow<T>但是,既然Cow是写入时复制,我将丢弃任何写入,这似乎在语义上是错误的.
Cow<T>抽象引用或拥有值的正确方法是什么?有比这更好的方法BorrowedOrOwned<T>吗?
我建议你使用a Cow,因为你BorrowedOrOwned没有区别,Cow只是它有更少的便利方法.获取BorrowedOrOwned对象的任何人都可以匹配它并获得拥有的值或对它的可变引用.如果您想避免混淆能够获得可变引用或对象本身,下面的解决方案也适用.
对于您的用例,我只是&T坚持,因为没有理由使API更复杂.如果用户想要一个usize,当T是usize,他们可以简单地取消引用参考.
如果您希望用户以自己的方式实际处理它,那么拥有的对象才有意义.即使在那时,Cow也是为了抽象你通过所有权传递的大/重物,以便不需要任何人clone.您的用例正好相反,您希望按所有权传递小对象,以防止用户需要复制小对象,而是复制它.