許多庫允許您定義一個類型,該類型實現給定的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
的關聯值。在處理程序中,您希望查找給定Token
的A
值,如果它尚未具有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);
}
這工作,但感覺有點克魯格-Y。它還介紹了爲每個方法調用移入和移出self
的開銷。
這樣做的最好方法是什麼?
!!!謝謝!我知道解構,但不知道你可以用它來同時獲得可變引用。這是一個巨大的幫助! – zslayton