代码之家  ›  专栏  ›  技术社区  ›  Hanzy

性状法中的锈寿命失配

  •  0
  • Hanzy  · 技术社区  · 5 年前

    我正在研究Rust book,并试图实现只允许将文本添加到博客中的逻辑 Post 如果它在 Draft 状态,可以找到 here (建议的练习之一)。

    其思想是使用结构和特征实现锈的状态模式。我只想将一个字符串片段传递给 add_text 如果不在 草稿 国家。然后我将重写 草稿 状态并返回为中的文本传入的字符串片段 草稿 国家。

    pub struct Post {
        state: Option<Box<dyn State>>,
        content: String,
    }
    
    impl Post {
        pub fn new() -> Post {
            Post {
                state: Some(Box::new(Draft {})),
                content: String::new(),
            }
        }
    
        pub fn add_text(&mut self, text: &str) {
            let text = self.state.as_ref().unwrap().add_text(text);
            // self.state.as_ref().unwrap().add_content(text)
            self.content.push_str(text);
        }
    
        //snip
    
    trait State {
        fn request_review(self: Box<Self>) -> Box<dyn State>;
        fn approve(self: Box<Self>) -> Box<dyn State>;
        fn content<'a>(&self, post: &'a Post) -> &'a str {
            ""
        }
        fn reject(self: Box<Self>) -> Box<dyn State>;
        fn add_text(&self, text: &str) -> &str {
            ""
        }
    }
    
    struct Draft {}
    
    impl State for Draft {
        fn request_review(self: Box<Self>) -> Box<dyn State> {
            Box::new(PendingReview {})
        }
        fn approve(self: Box<Self>) -> Box<dyn State> {
            self // don't want to approve a draft before review!
        }
        fn reject(self: Box<Self>) -> Box<dyn State> {
            self // reject doesn't do anything on a draft!
        }
        fn add_text(&self, text: &str) -> &str {
            text
        }
    }
    

    我在上面最后一个方法上得到了终身不匹配 添加文本 里面 impl State for Draft . 消息内容如下:

    lifetime mismatch
    
    ...but data from `text` is returned hererustc(E0623)
    lib.rs(67, 30): this parameter and the return type are declared with different lifetimes...
    lib.rs(67, 39):
    lib.rs(68, 9): ...but data from `text` is returned here
    

    我刚开始生锈,在这种情况下无法获得正确的寿命注释。我尝试了显式的终身注释,但没有帮助。另外,我知道既然其中一个推荐人是 &self 所有生存期参数的生存期应与 &自己 自动(我想?).

    有人能教我如何编译这段代码吗?这对以后使用这本书的人也可能有用。

    1 回复  |  直到 5 年前
        1
  •  2
  •   edwardw Neil Bartlett    5 年前

    你被绊倒了 lifetime elision rules :

    输入位置的每个省略的生存期都成为一个不同的生存期参数。

    如果只有一个输入生存期位置(省略或不省略),则该生存期将分配给所有省略的输出生存期。

    如果存在多个输入生存期位置,但其中一个是 &self &mut self ,生命周期 self 分配给所有省略的输出生存期。

    否则,省略输出生存期是错误的。

    在你的代码中 fn add_text(&self, text: &str) -> &str ,返回的 &str &自己 ,但实际上它是第二个参数。不匹配,好像是:

    fn add_text<'a, 'b>(&'a self, text: &'b str) -> &'a str {
        text
    }
    

    诀窍是在这里明确一生:

    trait State {
        fn add_text<'a>(&'a self, text: &'a str) -> &'a str;
    }
    
    impl State for Draft {
        fn add_text<'a>(&'a self, text: &'a str) -> &'a str {
            text
        }
    }
    

    如果您想要一个稍微普通一点的版本:

    trait State {
        fn add_text<'a, 'b: 'a>(&'a self, text: &'b str) -> &'a str;
    }
    
    impl State for Draft {
        fn add_text<'a, 'b: 'a>(&'a self, text: &'b str) -> &'a str {
            text
        }
    }
    

    这里写着只要 text 寿命 &自己 一切都很好。你决定额外的通用生命周期是否值得你费心。