Tutorial:
pub struct Post {
state: Option<Box<dyn State>>,
content: String,
}
Why is Option
needed here? By observing the entire source code, it is known that state
cannot be empty here, so according to my understanding, there is no need to use Option
here.
But when I remove the Option
, the following situation occurs.
pub fn request_review(&mut self) {
// if let Some(t) = self.state.take() {
// self.state = Some(t.request_review())
// }
self.state = self.state.request_review();
}
Compilation tips:
error[E0507]: cannot move out of `self.state` which is behind a mutable reference
--> src\lib.rs:26:22
|
26 | self.state = self.state.request_review();
| ^^^^^^^^^^ move occurs because `self.state` has type `Box<dyn State>`, which does not implement the `Copy` trait
It prompts that self.state
has moved. How can I solve this problem?
There is another problem. When should I use Option
and in which scenarios?
Complete source code
main.rs
use oop_exercise::Post;
fn main() {
let t = "I love China!";
let mut post = Post::new();
post.add_content(t);
assert_eq!("", post.content());
post.request_review();
assert_eq!("", post.content());
post.approve();
assert_eq!(t, post.content());
}
lib.rs
pub struct Post {
state: Option<Box<dyn State>>,
content: String,
}
impl Post {
pub fn new() -> Post {
Post {
state: Some(Box::new(DraftPost {})),
content: String::new()
}
}
pub fn add_content(&mut self, content: &str) {
self.content.push_str(content);
}
pub fn content(&self) -> &str {
self.state.as_ref().unwrap().content(self)
}
pub fn request_review(&mut self) {
if let Some(t) = self.state.take() {
self.state = Some(t.request_review())
}
}
pub fn approve(&mut self) {
if let Some(t) = self.state.take() {
self.state = Some(t.approve())
}
}
}
trait State {
fn content<'a>(&self, _post: &'a Post) -> &'a str {
""
}
fn request_review(self: Box<Self>) -> Box<dyn State>;
fn approve(self: Box<Self>) -> Box<dyn State>;
}
struct DraftPost {
}
struct PendingReviewPost {
}
struct PublishedPost {
}
impl State for DraftPost {
fn request_review(self: Box<Self>) -> Box<dyn State> {
Box::new(PendingReviewPost {})
}
fn approve(self: Box<Self>) -> Box<dyn State> {
self
}
}
impl State for PendingReviewPost {
fn request_review(self: Box<Self>) -> Box<dyn State> {
self
}
fn approve(self: Box<Self>) -> Box<dyn State> {
Box::new(PublishedPost {})
}
}
impl State for PublishedPost {
fn content<'a>(&self, post: &'a Post) -> &'a str {
post.content.as_str()
}
fn request_review(self: Box<Self>) -> Box<dyn State> {
self
}
fn approve(self: Box<Self>) -> Box<dyn State> {
self
}
}