如何修改成员函数

时间:2017-12-01 08:24:57

标签: rust

我有一个Struct结构,可选择包含SubStructSubStruct包含一个字段。 我想调用modify成员的Struct成员方法,该方法调用modify_field SubStruct成员方法修改field字段SubStruct }

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

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的可变借位。

1 个答案:

答案 0 :(得分: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);
}

当您使用structuremodify(&mut self)传递self.sub时,Option<SubStruct>仍然是if let,因此使用Some(sub)绑定对其进行解构会产生self }。但是,由于您只是可以随意借用Option,因此您需要阻止使用ref mut移动private static void SetProviderConnectionString(string connectionString) { var connectionStringFieldM = Membership.Provider.GetType().GetField("_sqlConnectionString", BindingFlags.Instance | BindingFlags.NonPublic); var connectionStringFieldR = Roles.Provider.GetType().GetField("_sqlConnectionString", BindingFlags.Instance | BindingFlags.NonPublic); var connectionStringFieldP = ProfileManager.Provider.GetType().GetField("_sqlConnectionString", BindingFlags.Instance | BindingFlags.NonPublic); connectionStringFieldM.SetValue(Membership.Provider, connectionString); connectionStringFieldR.SetValue(Roles.Provider, connectionString); connectionStringFieldP.SetValue(ProfileManager.Provider, connectionString); } public static void SetProviderUsers() { SetProviderConnectionString(ConfigurationManager.ConnectionStrings["users_cs"].ConnectionString); } public static void SetProviderApp() { SetProviderConnectionString(ConfigurationManager.ConnectionStrings["application_cs"].ConnectionString); } 的内容(正如您所做的那样)。