生成器模式 - 借来的价值不够长

and*_*man 1 rust

我正在努力实现一个简单的建设者,但却终身难忘.以下是给予error: borrowed value does not live long enough.这个问题似乎很相似.如果我存储t在一个可变变量然后调用s并最终确定它是有效的,但我想让一个衬里工作.我究竟做错了什么?

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

Vla*_*eev 10

问题是您正在Type使用基于Stringfrom 的字符串切片创建TypeBuilder,但是TypeBuilder创建的实例new()会立即在同一let语句中被销毁,因此如果允许,则字符串切片将变为悬空.这就是为什么它首先存储TypeBuilder在变量中的原因.

您对构建器的方法的问题在于构建器是它构建的值的数据的所有者:Type引用的内容TypeBuilder.这意味着Type实例总是与TypeBuilder实例绑定,而您无法创建Type和删除TypeBuilder.然而,这实际上是不自然的 - 建造者通常是临时物体,仅在施工期间是必需的.

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

struct Type {
    s: String,
}
Run Code Online (Sandbox Code Playgroud)

然后构建器应按值传递,然后通过finalize()以下方式使用:

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

这样,您的构建代码应该完全正常工作.

  • 使用`&mut self` /`&self`的方法在那里工作,因为那里的构建器只能使用`Copy`数据,而构建器构建的结构不包含对构建器的引用.它不适用于`String`s和其他种类的非可复制数据. (3认同)