如何将可变的自引用传递给特征方法?

m00*_*0am 7 rust

在学习Rust 书(第二版)的OOP 章节时,我承担了实现add_text以下结构的方法的可选任务

pub struct Post {
    state: Option<Box<State>>,
    content: String,
}
Run Code Online (Sandbox Code Playgroud)

有三个结构体实现了该State特征,但只有Draft结构体应该真正做一些事情。我的实现如下

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

我的问题是,为了State从我的 post 结构中调用该add_text方法,我一成不变地借用了self( in Post),并且无法传递对add_text特征方法的可变引用State

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
    }
}
Run Code Online (Sandbox Code Playgroud)

我该如何应对这个困境?我绝对需要对 的可变引用Post,否则我无法更改其文本。另一方面,我需要获得第State一个,否则我什至无法调用该方法。

解决此问题的一种方法是更改add_text​​为get_text_to_add不需要 的可变性Post,但我想确保我不会监督任何解决此问题的选项。

小智 4

对于结构,Rust 足够聪明,能够进行不相交的借用,因此您不需要传递对整个Post结构的可变引用,只需传递需要修改的部分(在本例中为内容)。

trait State {
    // snip

    // Modify the method on the add_text trait so that it
    // takes a mutable reference to String
    fn add_text(&self, content: &mut String, text: &str) { }
}

struct Draft { }

impl State for Draft {
    // snip

    // Update the implementation of State for Draft so that it
    // matches the new signature
    fn add_text(&self, content: &mut String, text: &str) {
        content.push_str(text);
    }
}

impl Post {
    // snip

    pub fn add_text(&mut self, text: &str){
        let state = self.state.as_ref().unwrap();  

        // Now when you call add_text you don't require a mutable 
        // reference to self, just to self.content and so the 
        // borrow checker is happy
        state.add_text(&mut self.content, text);  
    }
}
Run Code Online (Sandbox Code Playgroud)

这应该可行,但感觉有点强迫(因为 EvilTak 指出对 self 的引用Draft::add_text是多余的)。我想这就是练习的重点之一;虽然可以在 Rust 中实现 OOP 的某些模式,但还有更好的方法来对问题进行建模。