2017-11-18 38 views
3

我只是實現了一個簡單的特質,以保持一個結構屬性的歷史:我可以實現在Rust中向外部類型添加信息的特性嗎?

fn main() { 
    let mut weight = Weight::new(2); 
    weight.set(3); 
    weight.set(5); 
    println!("Current weight: {}. History: {:?}", weight.value, weight.history); 
} 

trait History<T: Copy> { 
    fn set(&mut self, value: T); 
    fn history(&self) -> &Vec<T>; 
} 

impl History<u32> for Weight { 
    fn set(&mut self, value: u32) { 
     self.history.push(self.value); 
     self.value = value; 
    } 
    fn history(&self) -> &Vec<u32> { 
     &self.history 
    } 
} 

pub struct Weight { 
    value: u32, 
    history: Vec<u32>, 
} 

impl Weight { 
    fn new(value: u32) -> Weight { 
     Weight { 
      value, 
      history: Vec::new(), 
     } 
    } 
} 

我不認爲這是可能的,但你可以在History特徵(或等價的東西)添加到一些東西,沒有按」 t已經有一個history屬性(如u32String),有效地加強了有關變量採用哪些值的一些信息?

回答

3

編號特徵不能將數據成員添加到現有結構。實際上,只有程序員可以通過修改結構的定義來做到這一點。包裝結構或散列表是要走的路。

2

不,性狀只能包含行爲,而不能包含數據。但是你可以創建一個結構體。

如果你能實現Historyu32,你必須保持整個歷史上的每u32對象無限,萬一有一天,有人決定把它.history()。 (另外,就當你將一個u32到另一個發生什麼呢?難道它的歷史隨之而來,或做新的價值只是被添加到列表中?)

相反,你可能希望能夠標記特定u32保留歷史記錄的對象。一個包裝結構,爲red75prime's answer建議,將工作:

mod hist { 
    use std::mem; 

    pub struct History<T> { 
     value: T, 
     history: Vec<T>, 
    } 

    impl<T> History<T> { 
     pub fn new(value: T) -> Self { 
      History { 
       value, 
       history: Vec::new(), 
      } 
     } 

     pub fn set(&mut self, value: T) { 
      self.history.push(mem::replace(&mut self.value, value)); 
     } 

     pub fn get(&self) -> T 
     where 
      T: Copy, 
     { 
      self.value 
     } 

     pub fn history(&self) -> &[T] { 
      &self.history 
     } 
    } 
} 

它是通用的,所以你可以有一個History<u32>History<String>或任何你想要的,但是當包裹類型爲Copyget()方法纔會被執行*。您的Weight類型可能只是History<u32>的別名。 Here it is in the playground.

將此代碼包裝到模塊中是保持抽象的必要部分。這意味着你不能寫weight.value,你必須致電weight.get()。如果value標記爲pub,則可以直接指定weight.value(繞過set),然後history將不準確。

作爲一個側面說明,你almost never&Vec<T>時可以使用&[T],所以我改變了history()簽名。你可能會考慮的另一件事是將迭代器返回到先前的值(可能是相反的順序)而不是片。


*獲得THistory<T>的更好的辦法是實施Deref,寫*foo而不是foo.get()

相關問題