下面是一个简单的模拟,场是一个矩形区域,其中有两个球在其中反弹。Field结构有一个update方法,对每个球调用update。在他们的update方法中,球需要根据它们的速度来移动。但它们也需要相互反应,以及场的边界

fn main() {
    let mut field = Field::new(Vector2d { x: 100, y: 100 });
    field.update();
}

#[derive(Copy, Clone)]
struct Vector2d {
    x: i32,
    y: i32,
}

struct Ball {
    radius: i32,
    position: Vector2d,
    velocity: Vector2d,
}

impl Ball {
    fn new(radius: i32, position: Vector2d, velocity: Vector2d) -> Ball {
        Ball {
            radius: radius,
            position: position,
            velocity: velocity,
        }
    }

    fn update(&mut self, field: &Field) {
        // check collisions with walls
        // and other objects
    }
}

struct Field {
    size: Vector2d,
    balls: [Ball; 2],
}

impl Field {
    fn new(size: Vector2d) -> Field {
        let position_1 = Vector2d {
            x: size.x / 3,
            y: size.y / 3,
        };
        let velocity_1 = Vector2d { x: 1, y: 1 };
        let position_2 = Vector2d {
            x: size.x * 2 / 3,
            y: size.y * 2 / 3,
        };
        let velocity_2 = Vector2d { x: -1, y: -1 };

        let ball_1 = Ball::new(1, position_1, velocity_1);
        let ball_2 = Ball::new(1, position_2, velocity_2);

        Field {
            size: size,
            balls: [ball_1, ball_2],
        }
    }

    fn update(&mut self) {
        // this does not compile
        self.balls[0].update(self);
        self.balls[1].update(self);
    }
}

如何将有关边界和另一个球的信息获取到Ball结构的更新函数?Field::update中的这些行不编译:
self.balls[0].update(self);
self.balls[1].update(self);

出现以下错误:
error[E0502]: cannot borrow `*self` as immutable because `self.balls[..]` is also borrowed as mutable
  --> src/main.rs:62:30
   |
62 |         self.balls[0].update(self);
   |         -------------        ^^^^- mutable borrow ends here
   |         |                    |
   |         |                    immutable borrow occurs here
   |         mutable borrow occurs here

我明白,但我不知道该怎么办。

最佳答案

当前,您的Ball结构需要知道它所包含的Field以便能够自我更新。这不会编译,因为结果将是循环引用和变异。您可以通过使用CellRefCell(后者有性能开销)来实现这一点,但最好以不同的方式构造代码。让Field结构检查并解决Ball-BallBall-Wall冲突。Ball结构的update函数可以处理更新Ball的位置。

// Ball's update function
fn update(&mut self) {
    // update position
}

// Field's update function
fn update(&mut self) {
    for ball in self.balls.iter_mut() {
        ball.update();
    }

    // check for collisions

    // resolve any collisions
}

关于rust - 将可变的自引用传递给拥有对象的方法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38944157/

10-12 06:54