如何在循环中使用链式构建器模式而不会产生编译器错误?

时间:2017-08-05 01:06:06

标签: rust

如何在循环中正确使用期望method chaining的构建器模式?使用log4rs中的示例。请注意self不是appender中的引用。

//builder pattern from log4rs

pub struct ConfigBuilder {
    appenders: Vec<Appender>,
    loggers: Vec<Logger>,
}

impl ConfigBuilder {
    pub fn appender(mut self, appender: Appender) -> ConfigBuilder {
        self.appenders.push(appender);
        self
    }
}

执行此操作会导致错误,因为(我认为)cb正在移动到.appender()返回的内存中。

let cb = ConfigBuilder::new();
for x in ys {
    cb.appender(x);
}

以下内容似乎有效。这是唯一的方法吗?

let mut cb = ConfigBuilder::new();
for x in ys {
    cb = cb.appender(x);
}

1 个答案:

答案 0 :(得分:4)

  

这是唯一的方法吗?

语义上它是关键的方式,虽然还有其他方法来编写它。 appender函数需要mut self,因此它将获取cb变量值的所有权,并使该变量在该点之后无法使用。它可以设计为借用参考,但链接很好。由于您处于循环中,因此构建器需要在下一次迭代时可用,因此您需要将值分配给新的。这意味着

let mut cb = ConfigBuilder::new();
for x in ys {
    cb = cb.appender(x);
}

确实是一种方法。另一种方法是使用Iterator's .fold来执行

let cb = ys.into_iter()
  .fold(ConfigBuilder::new(), |cb, x| cb.appender(x));

将所有内容保留在一个作业中,但在其他方面几乎完全相同。