我正在用 Rust 编写 Rogue-like。我有一个 Player
,它有一个 Vec
的盒装 TimedEffects
。定时效果有一个 activate(&mut Player)
和 deactivate(&mut Player)
方法,以及一个减少剩余时间的 tick()
方法.当它变为零时,应调用 deactivate()
方法。
pub struct Player {
timed_effects: Vec<Box<TimedEffect>>,
}
玩家每次移动,我都需要减少剩余时间。这是在 Player
方法中完成的:
impl Player {
fn regenerate(&mut self) {
self.timed_effects.iter_mut().for_each(|te| te.tick());
for i in 0..self.timed_effects.len() {
if self.timed_effects[i].ticks_remaining() == 0 {
let bte = self.timed_effects.swap_remove(i);
bte.deactivate(self);
}
}
}
}
我最初尝试将 self
参数 (&mut Player
) 传递给 TimedEffect
的 tick()
方法> 对象,具有在时间归零时自动调用 deactivate(player)
的逻辑。
迭代向量构成了对 (Player
) self
的借用,这与将 &mut Player
参数传递给 不兼容tick()
,甚至使用 .filter
进行单独的迭代。
相反,如图所示,我发现自己迭代了一个整数范围,将框从向量中提取到局部变量中,然后对其调用 .deactivate(self)
。
这很痛苦。
考虑到效果需要与其受害者有某种联系,以便 deactivate()
方法可以撤消效果,我应该如何构建这些对象,这样我才不会纠结于此依赖借用网络?
最佳答案
为了避免借用问题,您可以分两步进行:
- 将完成的效果从
timed_effects
转移到缓冲区, - 迭代缓冲区并调用
deactivate
。
我将使用 nightly 的 Vec::drain_filter
对于更流畅的代码,虽然它肯定不是强制性的。
fn regenerate(&mut self) {
self.timed_effects.iter_mut().for_each(|te| te.tick());
let timed_out: Vec<_> =
self.timed_effects
.drain_filter(|t| t.ticks_remaining() == 0)
.collect();
// Split iteration in a second step to stop borrowing self.
for timer in timed_out {
timer.deactivate(self);
}
}
为了进一步提高效率,您可以将可重用缓冲区传递给 regenerate
(以避免分配)。
关于rust - 如何处理相互依赖的 Rust 借用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49440876/