使用 to_owned() 是否是更新结构体的惯用方式?

kri*_*nab 4 struct method-chaining rust borrow-checker

我正在尝试使用链式方法更新 Rust 结构。我找到了一种方法来做到这一点,但我不确定我下面的代码是否是惯用的 Rust,而不仅仅是一种解决方法。

特别是,我.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);
Run Code Online (Sandbox Code Playgroud)

这是编写结构的就地修改的正确方法吗?如果我不在.to_owned()链的末尾包含该方法,则编译会失败并显示一条消息,提示临时变量的寿命不够长。

She*_*ter 5

您的代码“有效”,但对我来说没有意义。它:

  • 创造价值
  • 改变价值
  • 克隆值
  • 丢弃原始值

看到低效了吗?此外,所有“就地突变”都被完全丢弃,因此没有任何好处。

我通常会引入一个绑定来改变:

let mut data_capture = ModelDataCapture::new();
data_capture.set_run(0).set_year(1);
Run Code Online (Sandbox Code Playgroud)

或者一路走下去,创建一个具有某些等价物finishbuild

#[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);
}
Run Code Online (Sandbox Code Playgroud)

请参阅Rust 构建器模式是否必须使用冗余结构代码?有关镜像构建项目的构建器的更多示例。

您可以self在第一个示例中使用by-value,但在大多数情况下这很烦人,因为您总是必须记住绑定结果。