将可变的自引用传递给拥有对象的方法 [英] Passing mutable self reference to method of owned object

查看:31
本文介绍了将可变的自引用传递给拥有对象的方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

The following is a simple simulation with a field which is a rectangular area with two balls bouncing around in it. The Field struct has an update method, which calls update on each of the balls. The balls, in their update method, need to move around based on their velocity. But they also need to react to each other, as well as the boundaries of the field.:

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 中的这些行不会编译:

How do I get the information about the boundaries and the other ball to the Ball struct's update function? These lines in the Field::update do not compile:

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

我明白,但我不知道如何解决这个问题.

which I understand, but I don't know how to get around this.

推荐答案

目前你的 Ball 结构需要知道它所包含的 Field 以便能够自我更新.这不会编译,因为结果将是循环引用与突变相结合.您可以通过使用 CellRefCell(后者具有性能成本)来完成这项工作,但以不同的方式构建代码会更好.让 Field 结构检查并解析 Ball-BallBall-Wall碰撞.Ball 结构体的 update 函数可以处理更新 Ball 的位置.

Currently your Ball struct needs to know about the Field it's contained in to be able to update itself. This doesn't compile because the result would be cyclic references combined with mutation. You could make this work by using Cell or RefCell (the latter having a performance cost) but it would be even better to structure the code differently. Let the Field struct check for and resolve Ball-Ball and Ball-Wall collisions. The Ball struct's update function can handle updating the Ball's position.

// 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
}

这篇关于将可变的自引用传递给拥有对象的方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆