我正在尝试通过阅读The Rust Programming Language Book来学习Rust。我现在读到第17章,在状态模式的权衡结束时,你被要求做以下事情:
- 在将状态更改为Published之前,需要两次调用以进行批准。
你得到的代码是:
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) {
self.content.push_str(text);
}
pub fn content(&self) -> &str {
self.state.as_ref().unwrap().content(self)
}
pub fn request_review(&mut self) {
if let Some(s) = self.state.take() {
self.state = Some(s.request_review())
}
}
pub fn approve(&mut self) {
if let Some(s) = self.state.take() {
self.state = Some(s.approve())
}
}
}
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 {
""
}
}
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
}
}
struct PendingReview {}
impl State for PendingReview {
fn request_review(self: Box<Self>) -> Box<dyn State> {
self
}
fn approve(self: Box<Self>) -> Box<dyn State> {
Box::new(Published {})
}
}
struct Published {}
impl State for Published {
fn request_review(self: Box<Self>) -> Box<dyn State> {
self
}
fn approve(self: Box<Self>) -> Box<dyn State> {
self
}
fn content<'a>(&self, post: &'a Post) -> &'a str {
&post.content
}
}
所以我的理解是,在不破坏trait签名的情况下,你必须对PendingReview
实现某种逻辑,以便需要两次批准才能更改为Published
状态。
我想做点什么
struct PendingReview {
reviews: i32,
}
impl PendingReview {
fn add_review(&mut self) {
self.reviews += 1;
}
pub fn ready_to_approve(&self) -> bool {
if self.reviews == 2 {
return true;
}
add_review();
return false;
}
}
然后在PendingReview
状态的approve
函数中调用ready_to_approve
,但这不起作用,因为我需要一个可变引用,而我没有,而且我不能在不破坏trait签名的情况下拥有它。这种方法可能还有更多我看不到的问题,实际上我对Rust很陌生。
我真的不知道如何处理这个问题,所以任何帮助都很感激。
1条答案
按热度按时间xnifntxz1#
然后在
PendingReview
状态的approve
函数中调用ready_to_approve
,但这不起作用,因为我需要一个可变引用,而我没有,而且我不能在不破坏trait签名的情况下拥有它。这是不准确的。
State
trait的approve
函数不仅仅有一个可变引用-它拥有整个self
!你可以做任何你想做的事情,因为Rust的所有权总是排他性的。要在
approve
内部改变self
,您需要将其标记为mut
。但请注意,与将&self
更改为&mut self
不同,这不会影响签名。这就像有一个局部变量let x
,然后决定需要对其进行变异,并将其更改为let mut x
;它只是告诉编译器你希望发生变化,但它仍然是同一个变量,具有相同的类型-函数参数也是如此。考虑到这一点,
PendingReview
的approve
可以是:你的代码中还有一些其他问题需要修复:
ready_to_approve
需要&mut self
;1.调用
add_review()
是无效的,你必须说self.add_review()
.你可以自己看到它编译并且没有破坏trait的签名(playground)。