如何在Rust中迭代时调用一个方法

5

如果这很简单,我向你道歉。我正在学习Rust,并逐渐适应奇怪的借用系统。通常,通过改变方法调用的语法就可以获得所需的行为,但是,在这种情况下,似乎没有办法。

我的代码简化版本如下:EventPump 来自 SDL。

struct Example {
    pump: EventPump
}

impl Example {
    fn method(&mut self) {
        for event in pump.poll_iter() {
            self.other_method();
        }
    }

    fn other_method(&self) {

    }
}

然而,我遇到了以下错误:
error[E0502]: cannot borrow `*self` as immutable because it is also borrowed as mutable
  --> src\game.rs:53:67
   |
30 |             for event in self.pump.poll_iter();
   |                          ---------------------
   |                          | 
   |                          mutable borrow occurs here
   |                          mutable borrow later used here
...
53 |                  self.other_method();
   |                  ^^^^ immutable borrow occurs here

也许有一种正确的方法可以让我的结构体保持自身所有权,但我没有找到它。

我尝试过以下方法:

  • 将其转换为带有显式 while let event = iterator.next() 的 while 循环,仍然出现错误
  • 使函数变为可变函数,错误消息现在说不允许两个可变引用。我猜错误消息中的整个"不可变性"实际上是无关紧要的。

我可能可以将可迭代对象的整个内容复制到向量或类似的数据类型中,但这会破坏迭代器的目的,而且如果迭代器不是有限的怎么办?肯定有更好的方法吧...

如果有更多 Rust 经验的人能帮我解决问题,将不胜感激。

2个回答

4
如果您希望在同一代码块中有一个不可变结构体的情况下,该结构体的属性可变,您需要使用 RefCell。这被称为 内部可变性
如果需要 struct Example内部可变性,则需要使用 RefCell
use sdl2::{EventPump};

struct Example {
    pump: RefCell<EventPump> // wrap in RefCell
}

impl Example {
    // you have to decide whether you want a mutable or immutable chained methods
    // i.e. method and other_method should be of same mutability because
    // other method is called in method
    fn method(&self) {
        // borrow a mutable reference of pump inside a method with immutable self 
        let mut pump = self.pump.borrow_mut();
        for event in pump.poll_iter() {
            self.other_method();
        }
    }

    fn other_method(&self) {

    }
}

谢谢,那个可行。但是,现在如果我想要访问泵的另一个方法,我必须执行self.event_pump.as_ref().unwrap().as_ptr().as_ref().unwrap().keyboard_state(),这也是不安全的,所以并不理想。 - mousetail
@mousetail,不幸的是,你必须处理它成为RefCell的情况。你应该手动调用borrow()或borrow_mut()来使用它。 - Alan Darmasaputra

0
如果你有这样的一个模式:
fn method(&mut self) {
    for item in self.some_iterator_that_borrow_mut() {
        self.other_method();
    }
}

借用规则被打破,它声明了对self只有一个可变引用:现在有一个可变引用和一个不可变引用。

为了避免双重引用问题,需要消费迭代器并将项目收集到临时容器中,例如Vec中:

impl Example {
    fn method(&mut self) {
        for event in self.pump.poll_iter().collect::<Vec<_>>(); {
            self.other_method();
        }
    }

    fn other_method(&self) {}
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接