簡體   English   中英

我可以實現一個將信息添加到Rust中的外部類型的特征嗎?

[英]Can I implement a trait which adds information to an external type in Rust?

我剛剛實現了一個簡單的特性來保存struct屬性的歷史:

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特征(或類似的東西)添加到尚未具有history屬性的東西(如u32String ),有效地處理有關變量具有哪些值的一些信息有人嗎?

否。特征無法將數據成員添加到現有結構中。 實際上,只有程序員才能通過修改結構的定義來做到這一點。 包裝結構或散列表是可行的方法。

不,特征只能包含行為,而不能包含數據。 但你可以制作一個結構。

如果你可以為u32實現History ,你必須無限期地保留每個 u32對象的整個歷史記錄,以防有一天有人決定在它上面調用.history() (另外,當你將一個u32分配給另一個時會發生什么?它的歷史記錄是否附帶它,或新的值是否剛剛添加到列表中?)

相反,您可能希望能夠標記特定的 u32對象以保留歷史記錄。 正如red75prime的回答所示,包裝結構將起作用:

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>或任何您想要的內容,但get()方法僅在包裝類型為Copy 。*您的Weight類型可能只是History<u32>的別名History<u32> 這是在操場上。

將此代碼包裝在模塊中是維護抽象的必要部分。 這意味着你不能寫weight.value ,你必須調用weight.get() 如果value標記為pub ,則可以直接指定weight.value (繞過set ),然后history將不准確。

作為旁注,當你可以使用&[T]時,你幾乎不會想要&Vec<T> ,所以我改變了history()的簽名。 您可能會考慮的另一件事是返回迭代器而不是先前的值(可能是相反的順序)而不是切片。


*從History<T>中獲取T更好方法是實現Deref並編寫*foo而不是foo.get()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM