2016-12-14 51 views
2

我有一個特徵定義了一個可以保存值的對象的接口。性狀具有獲取當前值的方式:如何通過引用抽象爲值或值本身?

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>更好的方法?

+0

會返回一個關聯的類型'B:借用'工作嗎? –

+0

@ChrisEmerson我不確定這樣做的折衷是什麼,所以我不確定。你可以擴展一下嗎?這似乎是一個普遍有用的問題,所以即使他們沒有解決我的具體情況,我也會對所有答案感興趣。 –

+0

我覺得其實並沒有直接幫助。你最終還是需要像牛這樣的東西。 –

回答

7

我建議您使用Cow,因爲您的BorrowedOrOwnedCow沒有區別,只是它具有較少的便利方法。任何持有BorrowedOrOwned對象的人都可以匹配它並獲取擁有的值或可變引用。如果您想防止能夠獲取可變引用或對象本身的混淆,下面的解決方案也適用。

對於您的使用案例,我只需保留&T,因爲沒有理由讓API更復雜。如果用戶想要usize,則當Tusize時,他們可以簡單地解引用參考。

如果您希望用戶以自己的方式實際處理它,則擁有的對象纔有意義。即使如此,Cow的目的是爲了不要求任何人clone它通過所有權通過的大/重物體的抽象。您的使用案例正好相反,您想通過所有權傳遞小對象以防止用戶需要複製小對象,而是複製它。

+0

感謝您的建議。在簡化問題時,我錯誤地陳述了我有時想要返回'&T'的原因以及其他需要返回'T'的原因。如果實現在'Arc >(例如)中存儲'T',那麼不可能簡單地返回'&T'。必須克隆'T',並且由於克隆駐留在函數的堆棧上,所以不能返回對其的引用。我希望這有幫助。 PS。在RBR與你談話:) –

+1

啊!這更有意義。那麼..然後,我建議你的'BorrowedOrOwned'應該是'enum借入<'a, T> {Ref(&'a T),Arc(Arc >),Rc(Rc >)}'或者沿着這些線。它由'RefCell'變得複雜,因爲許多用例可能不需要'RefCell',但是如果不瞭解更多關於用例的信息,我想這可以解決它。 –

+0

非常真實。我將不得不一直使用它,但是我會將它標記爲答案,因爲你已經回答了關於「牛」的問題,這已經明確指出了我的正確方向。謝謝 –