2 回答

TA貢獻(xiàn)1864條經(jīng)驗(yàn) 獲得超6個(gè)贊
當(dāng)前,您的Ball結(jié)構(gòu)需要了解Field它所包含的內(nèi)容,以便能夠自我更新。這不會(huì)編譯,因?yàn)榻Y(jié)果將是循環(huán)引用與變異結(jié)合在一起。您可以通過(guò)使用Cell或RefCell(后者會(huì)降低性能)來(lái)完成這項(xiàng)工作,但最好以不同的方式構(gòu)造代碼。讓該Field結(jié)構(gòu)檢查并解決Ball- Ball和Ball- Wall沖突。該Ball結(jié)構(gòu)的update函數(shù)可以處理更新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
}

TA貢獻(xiàn)1946條經(jīng)驗(yàn) 獲得超3個(gè)贊
這是一個(gè)較小的示例:
struct Ball {
size: u8,
}
impl Ball {
fn update(&mut self, field: &Field) {}
}
struct Field {
ball: Ball,
}
impl Field {
fn update(&mut self) {
self.ball.update(self)
}
}
問(wèn)題
當(dāng)您傳遞對(duì)的引用時(shí)Field,您將保證Field不能更改(“不可變引用” 的不可變部分)。但是,此代碼也試圖改變它的一部分:球!self或field在實(shí)施中應(yīng)參考哪個(gè)參考Ball::update?
解決方案:僅使用您需要的字段
您可以將結(jié)構(gòu)所需的部分與不需要的部分分開(kāi),update并在調(diào)用update函數(shù)之前使用它們:
struct Ball {
size: u8,
}
impl Ball {
fn update(&mut self, field: &u8) {}
}
struct Field {
players: u8,
ball: Ball,
}
impl Field {
fn update(&mut self) {
self.ball.update(&self.players)
}
}
您甚至可以將這些零星的引用捆綁到一個(gè)整齊的包中:
struct Ball {
size: u8,
}
impl Ball {
fn update(&mut self, field: BallUpdateInfo) {}
}
struct BallUpdateInfo<'a> {
players: &'a u8,
}
struct Field {
players: u8,
ball: Ball,
}
impl Field {
fn update(&mut self) {
let info = BallUpdateInfo { players: &self.players };
self.ball.update(info)
}
}
或重組您的包含結(jié)構(gòu)以將信息與開(kāi)頭分開(kāi):
struct Ball {
size: u8,
}
impl Ball {
fn update(&mut self, field: &UpdateInfo) {}
}
struct UpdateInfo {
players: u8,
}
struct Field {
update_info: UpdateInfo,
ball: Ball,
}
impl Field {
fn update(&mut self) {
self.ball.update(&self.update_info)
}
}
解決方案:從中刪除成員 self
您也可以采用其他方法,Ball從中進(jìn)行刪除,F(xiàn)ield然后再對(duì)其進(jìn)行任何更改。如果您可以輕松/廉價(jià)地制造Ball,請(qǐng)嘗試更換它:
use std::mem;
#[derive(Default)]
struct Ball {
size: u8,
}
impl Ball {
fn update(&mut self, field: &Field) {}
}
struct Field {
ball: Ball,
}
impl Field {
fn update(&mut self) {
let mut ball = mem::replace(&mut self.ball, Ball::default());
ball.update(self);
self.ball = ball;
}
}
如果您不容易創(chuàng)建新值,則可以使用Optionand take:
struct Ball {
size: u8,
}
impl Ball {
fn update(&mut self, field: &Field) {}
}
struct Field {
ball: Option<Ball>,
}
impl Field {
fn update(&mut self) {
if let Some(mut ball) = self.ball.take() {
ball.update(self);
self.ball = Some(ball);
}
}
}
解決方案:運(yùn)行時(shí)檢查
您可以通過(guò)以下方式將借閱檢查移至運(yùn)行時(shí)而不是編譯時(shí)RefCell:
use std::cell::RefCell;
struct Ball {
size: u8,
}
impl Ball {
fn update(&mut self, field: &Field) {}
}
struct Field {
ball: RefCell<Ball>,
}
impl Field {
fn update(&mut self) {
self.ball.borrow_mut().update(self)
}
}
- 2 回答
- 0 關(guān)注
- 467 瀏覽
添加回答
舉報(bào)