学习Rust教程有关Option<T>的疑问?

作者站长头像
站长
· 阅读数 16

如题,代码如下:

pub struct Post {
    state: Option<Box<dyn State>>,
    content: String,
}

impl Post {
    // --snip--
    pub fn request_review(&mut self) {
        if let Some(s) = self.state.take() {
            self.state = Some(s.request_review())
        }
    }
}

trait State {
    fn request_review(self: Box<Self>) -> Box<dyn State>;
}

struct Draft {}

impl State for Draft {
    fn request_review(self: Box<Self>) -> Box<dyn State> {
        Box::new(PendingReview {})
    }
}

struct PendingReview {}

impl State for PendingReview {
    fn request_review(self: Box<Self>) -> Box<dyn State> {
        self
    }
}

关于这段代码:

pub fn request_review(&mut self) {
    if let Some(s) = self.state.take() {
        self.state = Some(s.request_review())
    }
}

教程上说:

我们需要将 state 临时设置为 None 来获取 state 值,即老状态的所有权,而不是使用 self.state = self.state.request_review(); 这样的代码直接更新状态值。这确保了当 Post 被转换为新状态后不能再使用老 state 值。

虽然教程上有做说明,但是我还是不能理解这里为什么是 “确保了当 Post 被转换为新状态后不能再使用老 state 值” , 麻烦再帮忙给解释解释,谢谢。

回复
1个回答
avatar
test
2024-07-17

在是状态模式嘛……可能和整个代码未来要实现的逻辑有关,也可能是考虑并发时的情况?

单从代码上看是这样的:

if let Some(s) = self.state.take() 这一句执行的时候,self.state 的所有权被转移到了 s 上,所以此时 self.state 已经是 None 了。

于是,在这个 if let 作用域中,包括之后的代码里,self.state 不再拥有旧值,因为旧值的所有权已经在 s 上了。

而如果使用 self.state = self.state.request_review(); 直接赋值,则在这个赋值的过程中,request_review() 返回之前,self.state 依然是旧值。

回复
likes
适合作为回答的
  • 经过验证的有效解决办法
  • 自己的经验指引,对解决问题有帮助
  • 遵循 Markdown 语法排版,代码语义正确
不该作为回答的
  • 询问内容细节或回复楼层
  • 与题目无关的内容
  • “赞”“顶”“同问”“看手册”“解决了没”等毫无意义的内容