【问题标题】:How to modify an optional field of a struct in a member function [duplicate]如何修改成员函数中结构的可选字段[重复]
【发布时间】:2017-12-01 08:24:56
【问题描述】:

我有一个结构Struct,可以选择包含SubStructSubStruct 包含一个字段。 我想调用Structmodify成员方法,调用SubStructmodify_field成员方法修改SubStructfield字段

这与提到的其他问题不同,因为它不是直接修改字段,而是调用成员方法反过来修改字段。直接修改字段有我见过的共享解决方案。

struct SubStruct {
    field: u32,
}

impl SubStruct {
    fn modify_field(&mut self) {
       self.field = 2
    }
}

struct Struct {
    sub: Option<SubStruct>,
}

impl Struct {
    fn modify(&mut self) {
        if let Some(ref mut sub) = self.sub { // no reference before Some
            sub.modify_field();

            self.do_something();
        }
    }

    fn do_something(&self) {
    }
}

fn main() {
    let sub = Some(SubStruct{field: 1});
    let mut structure = Struct{ sub };

    structure.modify();

    println!("{}", structure.sub.unwrap().field);
}

(playground

我尝试了许多变体,但都没有运气,我目前的版本遇到了这个错误:

error[E0502]: cannot borrow `*self` as immutable because `self.sub.0` is also borrowed as mutable
--> src/main.rs:20:13
   |
17 |         if let Some(ref mut sub) = self.sub { // no reference before Some
   |                          ----------- mutable borrow occurs here 
... 
20 |             self.do_something();    
   |             ^^^^ immutable borrow occurs here
21 |         }    |         - mutable borrow ends here

如您所见,它似乎与self.do_something() 采用self 的不可变借用有关,其中self 的可变借用已在函数参数中采用。

【问题讨论】:

  • 因为它不是直接修改字段,而是调用成员方法反过来修改字段 — 复制(加法)中使用的示例是 一个方法,特别是AddAssign trait
  • 好的,所以正如 ljedrez 下面提到的,我基本上需要重构以避免这种情况?
  • 此外,请frowned upon 更改您的问题,尤其是在问题得到回答(并接受!)之后。
  • 重复的消息特别要求我:“修改你的问题以澄清它与其他人的不同之处”(重复),其他人之前的编辑已经改变了操场上的错误消息,但这并没有t与代码重合....所以我更正了它。
  • 我将exact code you pasted here 复制到操场上,运行它,然后将生成的错误复制回问题中。如果它们以某种方式有所不同,我无法帮助您粘贴的代码不是您的意思。您的 original 代码和错误消息不一致,我已修复。无论如何,我现在已将此标记为许多“也借用”问题中的一些问题的重复。

标签: rust


【解决方案1】:

你已经很接近了:

impl Struct {
    fn modify(&mut self) {
        if let Some(ref mut sub) = self.sub { // no reference before Some
            sub.modify_field();
        }
    }
}

fn main() {
    let sub = Some(SubStruct { field: 1 });
    let mut structure = Struct { sub };

    structure.modify(); // no arguments, we are only working on self

    println!("{}", structure.sub.unwrap().field);
}

当您通过modify(&amp;mut self) 可变地借用structure 时,self.sub 仍然是Option&lt;SubStruct&gt;,因此使用if let 绑定解构它会产生Some(sub)。但是,由于您只是可变地借用self,因此您需要防止Option 的内容与ref mut 一起移动(就像您所做的那样)。

【讨论】:

  • 谢谢!这解决了这个例子,所以我接受了答案。现在让我尝试将它应用到我自己的真实(更复杂的例子)......
  • 我很害怕,我的简化示例太简化了......我想调用 Struct 的另一个方法,它给出了错误:“error[E0502]: cannot borrow *self as immutable因为self.sub.0 也被借用为可变的“我已经更新了操场代码..play.rust-lang.org/…
  • @AndrewMackenzie 你将无法在if let 绑定下的块中一成不变地借用self(即当可变借用生效时);不过,只要这适用于您的原始代码,您就可以在它之外执行此操作。如果没有,我建议使用更多原始代码提交一个新问题。
  • 谢谢,我担心这一点,并没有看到一个简单的解决方法。现在在操场上的代码有效地重现了这个问题 - 我没有你感兴趣的所有混乱。我想我需要重新考虑该代码... :-(
  • @AndrewMackenzie 老实说,它看起来不需要大量重构 - 即使这代表了问题,一些额外的代码可以帮助提出一些可能的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-04-18
  • 2019-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-15
  • 1970-01-01
相关资源
最近更新 更多