代码之家  ›  专栏  ›  技术社区  ›  user103716

使用来自结构本身的值更新结构时给出:“不能将`*self`作为可变项借用,因为它也是作为不可变项借用的”

  •  0
  • user103716  · 技术社区  · 5 年前

    我想创造一个 struct 这改变了它的 current_value 通过附加一些“常量”字符串 first_step 当 结构 第一次被创造出来。

    密码

    fn main() {
        let mut adder = Adder {
            current_value: "init".to_string(),
            first_step: ", first".to_string(),
        };
        adder.do_something()
    }
    
    struct Adder {
        current_value: String,
        first_step: String,
    }
    
    impl Adder {
        fn add(&mut self, value: &String) {
            self.current_value = format!("{}{}", self.current_value, value);
        }
    
        fn do_something(&mut self) {
            // cannot borrow `*self` as mutable because it is also borrowed as immutable
            // mutable borrow occurs here rustc(E0502)
            // main.rs(24, 18): immutable borrow occurs here
            // main.rs(24, 14): immutable borrow later used by call
            self.add(&self.first_step);
        }
    }
    

    playground

    我认为错误很明显 self 在里面 self.add 由于 add 有 &mut self ,但要追加的值也来自 自己 ,但这一次,借来的是不变的,我们不能借来 自己 可变和不变)。

    但我不知道如何解决这个问题,创建一个数据结构,它可以用一些“常量”值更新自身,这些值是在创建结构时定义的。在现实生活中,我有一个 结构 包含两个 file 和 file_header: String ,我想有一个方法来写 file_header 进入 文件 .

    0 回复  |  直到 5 年前
        1
  •  2
  •   Kevin Reid    5 年前

    锈 做 允许借钱 部分 一个 struct 单独调用,但当调用一个函数/方法时 &mut Self ,这总是借用整个 结构 函数体永远不会用作附加信息。所以,解决问题的一个方法是重写函数签名,使其 做 掌握必要的信息。

    impl Adder {
        /// Algorithm implementation; takes all components explicitly.
        /// Is not a method.
        fn add_impl(current_value: &mut String, add_value: &str) {
            current_value.push_str(add_value);
        }
    
        /// Method for external use — less flexible, but simple.
        pub fn add(&mut self, value: &str) {
            Self::add_impl(&mut self.current_value, value);
        }
    
        fn do_something(&mut self) {
            Self::add_impl(&mut self.current_value, &self.first_step);
        }
    
    }
    

    您的描述——一个可以用一些“常量”值更新自身的数据结构,这些值是在创建结构本身时定义的——表明您可能面临比这个简单示例更复杂的情况。如果您有多个需要更新的可变字段(或者即使您真的想使用方法语法),您可以进行另一个 结构 它包含正确的字段子集,然后是 do_something 可以称之为普通 &mut self 内部结构上的方法。

    struct FancyAdder {
        first_step: String,
        data: AdderData,
    }
    
    struct AdderData {
        current_value: String,
        ...
    }
    
    impl FancyAdder {
        fn do_something(&mut self) {
           // This borrows `self.data` mutably and `self.first_step` immutably.
           // No overlap.
           self.data.add(&self.first_step);
        }
    }
    
    impl AdderData {
        fn add(&mut self, value: &str) {
            self.current_value.push_str(value);
        }
    }