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

如题,代码如下:

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.7k
2 个回答

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

单从代码上看是这样的:

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 依然是旧值。

if let Some(s) = self.state.take() {
        self.state = Some(s.request_review())   
 }  //create new box; heap address different
self.state = self.state.request_review(); //box moved ;
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进