调用字段的函数并在Rust中传递自身(& S)

dxxyhpgq  于 2022-11-12  发布在  其他
关注(0)|答案(3)|浏览(78)

我有一个MainStruct,它拥有HelperStruct的一个示例。我想创建一个方法来调用helper的方法。但是helper的方法确实需要(不可变的)访问MainStruct

struct MainStruct {
    helper: HelperStruct,
}

impl MainStruct {
    pub fn call_helper(&mut self, args) { 
        // &mut self because the_method changes inner state of HelperStruct
        self.helper.the_method(self, args)
    }
}

impl HelperStruct {
    pub fn the_method(&mut self, owner: &MainStruct, args) {
        owner.other_method();
    }
}

有了这样的安排

error[E0502]: cannot borrow `self.helper` as mutable because it is also borrowed as immutable
214 |         self.helper.the_method(self, args)
    |         ^^^^^^^^^^^^----------^----^^^^^^^^^^^^^^^^^^^^^^
    |         |           |            |
    |         |           |            immutable borrow occurs here
    |         |           immutable borrow later used by call
    |         mutable borrow occurs here

至关重要的是,MainStruct仍然是与功能交互的主要接口(因此,Helper自己的Main不是一个选项)。
我应该如何重新构造代码(或者使用智能指针?),以便我可以从Helper内部与所有者交互?而且,可以保证the_method()只在MainStruct的示例内部调用。

实际上下文:

MainStruct是我的游戏的FieldHelperStruct是处理路径的类,主要是A*。A* 有很多存储其状态的大型数组。A* 通过后,只有其中的一些 * 需要 * 重新初始化(或清理)。
最后我调用了A* 很多次,所以我想避免在每次调用时都完全重新初始化它。所以我将它存储在Field中,并且只在一次调用后才调用reset()
为了正确地规划路径,A* 需要查看Field(障碍物等)。

pub fn full_pathing(&mut self, field: &Field, source: (i32, i32), destination: (i32, i32))

需要具有&mut self

ngynwnxp

ngynwnxp1#

你可以让the_method成为一个关联函数,并让它只接收一个&mut MainStruct,它必须通过这个引用来访问它自己:

struct MainStruct {
    helper: HelperStruct,
}

impl MainStruct {
    pub fn call_helper(&mut self, args) { 
        HelperStruct::the_method(self, args)
    }
}

impl HelperStruct {
    pub fn the_method(main: &mut MainStruct, args) {
        main.other_method();

        //Access helper like this:
        main.helper.whatever();
    }
}

或者,如果您的两个结构体相互交织在一起,您可以将它们组合成一个结构体。

emeijp43

emeijp432#

你需要让Rust相信,无论HelperStructMainStruct做什么,它都不会试图通过 * MainStruct * 访问自己 *,因为这构成了对某个东西的不可变引用,而你也有一个可变引用。
根据HelperStruct的复杂性和需求,一种选择是将一个虚拟的HelperStructswapMainStruct中,然后在(现已隔离的)HelperStruct上调用该函数。

use std::mem::swap;

struct MainStruct {
    helper: HelperStruct,
}

impl MainStruct {
    pub fn call_helper(&mut self, args) { 
        let mut helper_struct = HelperStruct::default(); // Some dummy value
        swap(&mut helper_struct, &mut self.helper);
        helper_struct.the_method(self, args);
        swap(&mut helper_struct, &mut self.helper);
    }
}

这样一来,HelperStruct.the_method就可以不可变地访问MainStruct * 的所有内容,除了 * 本身,它被临时填充掉了。

6qfn3psc

6qfn3psc3#

self传递给the_method将不可变地借用helper,但方法调用本身也将可变地借用它。

pub fn the_method(&self, owner: &MainStruct, args)

如果你需要the_method来获取一个对self的可变引用,你需要考虑重构你的代码。

相关问题