Есть ли способ передать & mut self от метода, который сам принимает & mut self? - PullRequest
0 голосов
/ 22 апреля 2020

У меня есть эта структура State, которая содержит Box<dyn Runmode>. режим выполнения должен быть в состоянии переключаться, и когда он переключается, старый режим запуска выгружается (он освобождает свои ресурсы и сбрасывает некоторое состояние), затем окно, содержащее режим выполнения, переназначается, и загружается новый режим выполнения. При загрузке режима выполнения он должен иметь возможность доступа к структуре State для изменения и / или чтения некоторых вещей, которые необходимы для правильной работы режима выполнения, а при выгрузке он должен иметь возможность сбрасывать это состояние. Вот мой код:

trait Runmode {
    fn load(&mut self, state: &mut State);
    ...
    fn unload(&mut self, state: &mut State);
}

struct State {
    runmode: Box<dyn Runmode>,
    ...
}

impl State {
    pub fn set_runmode(&mut self, mut new_runmode: Box<dyn Runmode>) {
        self.runmode.unload(self);
        // the line above causes errors

        self.runmode = new_runmode;

        self.runmode.load(self);
        // this line also causes errors
    }
}

, как вы, возможно, знаете, это вызывает проблему множественных изменяемых ссылок на один объект, что недопустимо. Но я действительно не вижу другого пути решения этого. Черт, даже это не скомпилируется:

fn switch_runmode(mut state: State, mut new_runmode: Box<dyn Runmode>) {
    state.runmode.unload(&mut state);

    state.runmode = new_runmode;

    state.runmode.load(&mut state);
}

Что я здесь забыл? Во втором примере также написано, что я заимствую изменяемый дважды, но единственные изменяемые заимствования, которые я получаю, это когда я загружаю и выгружаю режим выполнения, а затем есть только одна изменяемая ссылка, которая входит в метод runmodes.

1 Ответ

1 голос
/ 22 апреля 2020

Предполагая, что load и unload не изменяют state.runmode, вы можете разделить State на две части: runmode и nonrunmode:

struct State {
    runmode: Box<dyn Runmode>,
    nonrunmode: NonRunMode, // contains everything else
}

Тогда unload и load могут принимать &mut NonRunMode в качестве аргументов.

trait Runmode {
    fn load(&mut self, state: &mut NonRunMode);
    ...
    fn unload(&mut self, state: &mut NonRunMode);
}

Это должно дать понять компилятору, что изменяются только отдельные части State.

...