建造者模式——借来的价值活得不够久 [英] Builder pattern - borrowed value does not live long enough

查看:38
本文介绍了建造者模式——借来的价值活得不够久的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试实现一个简单的构建器,但在生命周期中挣扎.以下给出了错误:借来的价值寿命不够长.这个问题似乎很相似.如果我将 t 存储在一个可变变量中,然后调用 s 并完成它的工作,但我想让一个班轮工作.我究竟做错了什么?

I'm trying to implement a simple builder but struggling with lifetimes. The following is giving error: borrowed value does not live long enough. This question seems similar. If I store t in a mutable variable and then call s and finalize it works, but I want to get the one liner to work. What am I doing wrong?

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);
}

推荐答案

问题是您正在使用基于 String 的字符串切片创建 Typecode>TypeBuilder,但是用 new() 创建的 TypeBuilder 实例会在同一个 let 语句中立即销毁,所以如果这是如果允许,字符串切片将变得悬空.这就是为什么当您首先将 TypeBuilder 存储在变量中时它会起作用的原因.

The problem is that you're creating Type with a string slice based on a String from TypeBuilder, but TypeBuilder instance created with new() is destroyed immediately in the same let statement, so if this was allowed, the string slice would became dangling. And that's why it works when you store TypeBuilder in a variable first.

您对构建器的方法的问题在于,构建器是它构建的值的数据的所有者:Type 引用了 TypeBuilder 的内容.这意味着 Type 实例总是绑定到 TypeBuilder 实例,并且你不能创建 Type 并删除 TypeBuilder.然而,这真的很不自然 - 构建器通常是临时对象,仅在构建期间才需要.

The problem with your approach to the builder is that the builder is the owner of data for the value it builds: Type references the contents of TypeBuilder. This means that Type instances are always tied to TypeBuilder instances, and you just cannot create Type and drop TypeBuilder. However, this is really unnatural - builders are usually transient objects which are only necessary during construction.

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

Consequently, in order for the builder pattern to work correctly your Type must become the owner of the data:

struct Type {
    s: String,
}

那么builder应该通过值传递,然后被finalize()消耗:

Then the builder should be passed by value and then consumed by 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 }
    }
}

这样您的构建代码就应该完全按照原样工作.

This way your building code should work exactly as it is.

这篇关于建造者模式——借来的价值活得不够久的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆