许多库允许您定义实现给定 trait
的类型用作回调处理程序。这需要您将处理事件所需的所有数据集中在一个数据类型中,这会使借用变得复杂。
例如, mio
允许您实现 Handler
并在您 run the EventLoop
时提供您的结构.考虑一个具有这些普通数据类型的示例:
struct A {
pub b: Option<B>
};
struct B;
struct MyHandlerType {
pub map: BTreeMap<Token, A>,
pub pool: Pool<B>
}
您的处理程序有来自 Token
的 map 到 A
类型的项目.每项类型 A
可能已经或可能没有类型为 B
的关联值.在处理程序中,您想查找 A
给定 Token
的值而且,如果它还没有 B
值,从处理程序的 Pool<B>
中取出一个.
impl Handler for MyHandlerType {
fn ready(&mut self, event_loop: &mut EventLoop<MyHandlerType>,
token: Token, events: EventSet) {
let a : &mut A = self.map.get_mut(token).unwrap();
let b : B = a.b.take().or_else(|| self.pool.new()).unwrap();
// Continue working with `a` and `b`
// ...
}
}
在这种排列中,尽管从直觉上可以看出 self.map
和 self.pool
是不同的实体,借用检查员提示 self
当我们去访问 self.map
时已经借了(通过 self.pool
) .
一种可能的方法是将每个字段包装在 MyHandlerType
中在Option<>
.然后,在方法调用开始时,take()
这些值来自 self
并在通话结束时恢复它们:
struct MyHandlerType {
// Wrap these fields in `Option`
pub map: Option<BTreeMap<Token, A>>,
pub pool: Option<Pool<B>>
}
// ...
fn ready(&mut self, event_loop: &mut EventLoop<MyHandlerType>,
token: Token, events: EventSet) {
// Move these values out of `self`
let map = self.map.take().unwrap();
let pool = self.pool.take().unwrap();
let a : &mut A = self.map.get_mut(token).unwrap();
let b : B = a.b.take().or_else(|| self.pool.new()).unwrap();
// Continue working with `a` and `b`
// ...
// Restore these values to `self`
self.map = Some(map);
self.pool = Some(pool);
}
这可行,但感觉有点笨拙。它还引入了将值移入和移出 self
的开销。对于每个方法调用。
执行此操作的最佳方法是什么?
最佳答案
要同时获取对结构不同部分的可变引用,请使用解构。示例 here .
struct Pair {
x: Vec<u32>,
y: Vec<u32>,
}
impl Pair {
fn test(&mut self) -> usize {
let Pair{ ref mut x, ref mut y } = *self;
// Both references coexist now
return x.len() + y.len();
}
}
fn main() {
let mut nums = Pair {
x: vec![1, 2, 3],
y: vec![4, 5, 6, 7],
};
println!("{}", nums.test());
}
关于struct - 同时改变多个结构字段的最快惯用方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32403895/