下面是一个简单的模拟,场是一个矩形区域,两个球在其中弹跳.Field struct 有一个update方法,在每个球上调用update.在update法中,球需要根据其速度四处移动.但他们也需要对彼此以及领域的边界做出react

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 struct的更新函数中?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 struct 需要了解它所包含的Field,以便能够self 更新.因为循环引用不会与循环引用合并.您可以通过使用CellRefCell(后者有性能成本)来实现这一点,但更好的做法是以不同的 struct 构建代码.让Field struct 判断并解决Ball-BallBall-Wall冲突.Ball struct的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相关问答推荐

关于Rust 中回归的逻辑

在不重写/专门化整个函数的情况下添加单个匹配手臂到特征的方法?

如何实现泛型枚举的`Serde::Desialize`特性

通过不同的字段进行散列和排序的 struct (需要不同的EQ实现)

铁 rust 中的泛型:不能将`<;T作为添加>;::Output`除以`{Float}`

如何高效地将 struct 向量中的字段收集到单独的数组中

在IntoIter上调用.by_ref().Take().rev()时会发生什么情况

我可以在不收集或克隆的情况下,将一个带有Item=(key,val)的迭代器拆分成单独的key iter和val iter吗?

如何在嵌套的泛型 struct 中调用泛型方法?

为什么BufReader实际上没有缓冲短寻道?

为什么 GAT、生命周期和异步的这种组合需要 `T: 'static`?

使用启用优化的 alloc 会导致非法指令崩溃

‘&T as *const T as *mut T’ 在 ‘static mut’ 项目中合适吗?

在发布中包含 Rust DLL

rust tokio::spawn 在 mutexguard 之后等待

为什么我不能克隆可克隆构造函数的Vec?

改变不实现克隆的 dioxus UseState struct

通用函数中的生命周期扣除和borrow (通用测试需要)

将文件的第一行分别读取到文件的其余部分的最有效方法是什么?

在同一向量 Rust 中用另一个字符串扩展一个字符串