许多库允许您定义实现给定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
到A
类型的项目的地图。类型A
的每个项目可能已经或可能没有类型B
的关联值。在处理程序中,您希望查找给定A
的{{1}}值,如果它还没有Token
值,请从处理程序{{1}中获取一个值}}
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()
这可行,但感觉有点kluge-y。它还引入了为每个方法调用移入和移出self
值的开销。
最好的方法是什么?
答案 0 :(得分:13)
要同时获取结构的不同部分的可变引用,请使用destructuring。示例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());
}