关于rust:Builder模式-借入的价值寿命不足

Builder pattern - borrowed value does not live long enough

我正在尝试实现一个简单的生成器,但是却要竭尽全力。 以下是error: borrowed value does not live long enough。 这个问题似乎很相似。 如果我将t存储在一个可变变量中,然后调用s并最终确定它可以正常工作,但是我想让一个衬板工作。 我究竟做错了什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
struct Type<'a> {
    s: &'a String,
}

struct TypeBuilder {
    s: String,
}

impl TypeBuilder {
    fn new() -> TypeBuilder {
        TypeBuilder { s:"".to_string() }
    }

    fn s(&mut self, s: String) -> &mut TypeBuilder {
        self.s = s;
        self
    }

    fn finalize(&self) -> Type {
        Type { s: &self.s }
    }
}

fn main() {
    let t = TypeBuilder::new()
                    .s("a".to_string())
                    .finalize();
    println!("string: {}", t.s);
}

问题是您要使用基于TypeBuilderString的字符串切片来创建Type,但是使用new()创建的TypeBuilder实例会在同一let语句中立即销毁,因此如果被允许,字符串切片将变得悬而未决。这就是为什么先将TypeBuilder存储在变量中时它起作用的原因。

使用构建器的方法存在的问题是,构建器是其构建的值的数据所有者:Type引用TypeBuilder的内容。这意味着Type实例始终与TypeBuilder实例绑定,并且您无法创建Type并删除TypeBuilder。但是,这确实是不自然的-生成器通常是临时对象,仅在构建期间才需要。

因此,为了使构建器模式正确运行,您的Type必须成为数据的所有者:

1
2
3
struct Type {
    s: String,
}

然后,应该按值传递构建器,然后按finalize()使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
impl TypeBuilder {
    fn new() -> TypeBuilder {
        TypeBuilder { s:"".to_string() }
    }

    fn s(mut self, s: String) -> TypeBuilder {
        self.s = s;
        self
    }

    fn finalize(self) -> Type {
        Type { s: self.s }
    }
}

这样,您的建筑代码应该可以完全正常工作。