While working through the OOP-Chapter of the Rust book (2nd Edition) I took on the optional task to implement the method add_text
for the following struct
pub struct Post {
state: Option<Box<State>>,
content: String,
}
There are three structs that implement the State
trait, but only the Draft
struct should actually do something. I implemented this as follows
trait State {
// snip
fn add_text(&self, post: &mut Post, text: &str) { }
}
struct Draft { }
impl State for Draft {
// snip
fn add_text(&self, post: &mut Post, text: &str) {
post.content.push_str(text);
}
}
My problem is that in order to get the State
from my post struct to call the add_text
method I immutably borrow self
(in Post
) and can not pass on a mutable reference to the add_text
method of the State
trait:
impl Post {
// snip
pub fn add_text(&mut self, text: &str){
let state = self.state.as_ref().unwrap(); // This immutably borrows self
state.add_text(self, text); // so that this mutable borrow is no longer possible
}
}
How do I deal with this dilemma? I definitely need a mutable reference to the Post
, otherwise I can't change its text. On the other hand, I need to get the State
first since otherwise I can not even call the method.
One way to work around this would be be to change add_text
to get_text_to_add
which would not require mutability of the Post
, but I would like to make sure that I am not overseeing any options to solve this.
State::add_text
method impl onDraft
has nothing to do with theDraft
struct whatsoever - you might as well remove the&self
parameter and be done with it. Second, as an external consumer of this hypothetical library I'd expect theadd_text
method to be on thePost
struct itself. You would be much better off movingadd_text
toPost
, and looking up information or mutating thestate
field as and when needed. If you only want toadd_text
if the post is a draft, you can check ifself.state
is aDraft
insidePost::add_text
. – EvilTak