2017-05-16 28 views
3

我正在玩弄使用鏈式方法更新Rust結構。我找到了一種方法來做到這一點,但我不確定下面的代碼是否是慣用的Rust,而不僅僅是一種解決方法。正在使用to_owned()慣用的方式來更新一個結構?

特別是,我在鏈接方法的末尾使用了.to_owned()來返回借用結構。代碼編譯和工作得很好。這是最簡單的例子。

//struct.rs 
#[derive(Debug, Default, Clone, PartialEq)] 
pub struct ModelDataCapture { 
    run: i32, 
    year: i32, 
} 
impl ModelDataCapture { 
    pub fn new() -> Self { 
     ModelDataCapture::default() 
    } 
    pub fn set_run(&mut self, run: i32) -> &mut ModelDataCapture { 
     self.run = run; 
     self 
    } 
    pub fn set_year(&mut self, year: i32) -> &mut ModelDataCapture { 
     self.year = year; 
     self 
    } 
} 

//main.rs 
let data_capture = ModelDataCapture::new() 
    .set_run(0) 
    .set_year(1) 
    .to_owned(); // <<< QUESTION 

println!("here is the data capture {:?}", data_capture); 

這是寫這個就地修改結構的正確方法嗎?如果我在鏈的末尾沒有包含.to_owned()方法,則編譯將失敗並顯示消息:臨時變量的存活時間不夠長。

+1

你可能會對這個箱子感興趣https://github.com/colin-kiegel/rust-derive-builder#how-it-works :) – kennytm

+0

@kennytm謝謝你的提示。是的,我看到那個箱子,只是在我開始使用快捷方式之前試圖寫自己的建造者:)。但我會研究一下派生構建器的箱子。我只是想確保我可以包含我想包含的輸入驗證邏輯。 – krishnab

回答

3

你的代碼「有效」,但對我沒有意義。它:

  • 創建值
  • 器變化了價值
  • 克隆的價值
  • 扔掉原來的值

見效率低下?另外,所有的「就地突變」都被完全拋棄了,所以沒有任何好處。

我通常引入結合結構變異:

let mut data_capture = ModelDataCapture::new(); 
data_capture.set_run(0).set_year(1); 

還是一路走,並創建具有的finish一些相當或build

#[derive(Debug)] 
struct ModelDataCapture { 
    run: i32, 
    year: i32, 
} 

#[derive(Debug, Default)] 
struct ModelDataCaptureBuilder { 
    run: i32, 
    year: i32, 
} 

impl ModelDataCaptureBuilder { 
    fn set_run(self, run: i32) -> Self { 
     ModelDataCaptureBuilder { run, ..self } 
    } 

    fn set_year(self, year: i32) -> Self { 
     ModelDataCaptureBuilder { year, ..self } 
    } 

    fn build(self) -> ModelDataCapture { 
     let ModelDataCaptureBuilder { run, year } = self; 
     ModelDataCapture { run, year } 
    } 
} 

fn main() { 
    let data_capture = ModelDataCaptureBuilder::default().set_run(0).set_year(1).build(); 

    println!("here is the data capture {:?}", data_capture); 
} 

更多的例子,請參見Do Rust builder patterns have to use redundant struct code?建設者的建築商鏡像建築物。

您可以在第一個示例中按值更改self,但這在大多數情況下很煩人,因爲您必須始終記住要綁定結果。

+0

好吧,太棒了。是的,當我在綁定之前鏈接方法時,我明白你的意思是創建,變異,克隆想法。這就是爲什麼我想知道奇怪的'.to_owned()'方法。謝謝你的提示。我開始比以前更好地掌握這一點。 – krishnab

+0

直接使用消耗對象的setter中的移動語義不是更好嗎?即將'set_run'定義爲'fn set_run(mut self,run:i32) - > Self {self.run = run;自我},等等。儘管編譯器可能足夠聰明,可以同時優化兩個輸出,但更明確地說,更新單個字段感覺更高效,更清晰。 – user4815162342

相關問題