【问题标题】:How to pass a mutable self reference on to a trait method?如何将可变的自引用传递给特征方法?
【发布时间】:2018-02-23 18:18:07
【问题描述】:

在阅读 Rust 书(第 2 版)的 OOP-Chapter 时,我承担了可选任务来为以下结构实现方法 add_text

pub struct Post {
    state: Option<Box<State>>,
    content: String,
}

有三个结构体实现了State trait,但只有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);
    }
}

我的问题是,为了从我的 post 结构中获取 State 以调用 add_text 方法,我不可变地借用 self(在 Post 中)并且不能传递对 @987654331 的可变引用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
    }
}

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

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

【问题讨论】:

  • 这对我来说看起来像代码味道。首先,Draft 上的 State::add_text 方法 impl 与 Draft 结构 whatsoever 无关 - 您不妨删除 &amp;self 参数并完成它。其次,作为这个假设库的外部使用者,我希望 add_text 方法位于 Post 结构本身上。您最好将add_text 移动到Post,并在需要时查找信息或更改state 字段。如果你只想add_text,如果帖子是草稿,你可以检查self.state是否是Draft里面Post::add_text

标签: rust


【解决方案1】:

对于结构,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);  
    }
}

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

【讨论】:

  • 谢谢,我没有想到这种方法。我同意你和@EvilTak 的观点,这很可能是一种不好的方法(因此,我的问题的最后一段)。另一方面,这是一个了解更多关于借贷的好机会,所以感谢您帮助我。我会在星期一接受答复。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-09
  • 2017-03-11
  • 2015-06-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多