2015-04-27 65 views
4

內:訪問HashMap的字段值作爲與MUT給出一個簡單的結構類似這樣的結構IMPL

struct Server { 
    clients: HashMap<usize, Client> 
} 

什麼是訪問Client作爲&mut的最佳方式?請看下面的代碼:

use std::collections::HashMap; 

struct Client { 
    pub poked: bool 
} 

impl Client { 
    pub fn poked(&self) -> bool { 
    self.poked 
    } 

    pub fn set_poked(&mut self) { 
    self.poked = true; 
    } 
} 

struct Server { 
    clients: HashMap<usize, Client> 
} 

impl Server { 
    pub fn poke_client(&mut self, token: usize) { 
    let client = self.clients.get_mut(&token).unwrap(); 
    self.poke(client); 
    } 

    fn poke(&self, c: &mut Client) { 
    c.set_poked(); 
    } 
} 

fn main() { 
    let mut s = Server { clients: HashMap::new() }; 
    s.clients.insert(1, Client { poked: false }); 

    s.poke_client(1); 

    assert!(s.clients.get(&1).unwrap().poked() == true); 
} 

只有兩個選擇我看到的是使用RefCell/Cell內部客戶端,這讓事情看起來很可怕:

pub struct Client { 
    nickname: RefCell<Option<String>>, 
    username: RefCell<Option<String>>, 
    realname: RefCell<Option<String>>, 
    hostname: RefCell<Option<String>>, 
    out_socket: RefCell<Box<Write>>, 
} 

或者包裹clientsRefCell,其中使得不可能有這樣的簡單方法Server

pub fn client_by_token(&self, token: usize) -> Option<&Client> { 
    self.clients_tok.get(&token) 
} 

迫使我使用閉包(例如with_client_by_token(|c| ...))。

+0

生鏽的風格指南是4空間縮進。 – Shepmaster

回答

1

由於錯誤消息說,您不能reborrow self的時候已經是性情不定地借:

<anon>:24:5: 24:9 error: cannot borrow `*self` as immutable because `self.clients` is also borrowed as mutable 
<anon>:24  self.poke(client); 
       ^~~~ 

在你的方法:

pub fn poke_client(&mut self, token: usize) { 
    let client = self.clients.get_mut(&token).unwrap(); 
    self.poke(client); 
} 

你性情不定地在第一行借self,然後嘗試再次借用第二行,當您調用方法poke時。最簡單的辦法是隻調用Client::set_poked這裏:

pub fn poke_client(&mut self, token: usize) { 
    let client = self.clients.get_mut(&token).unwrap(); 
    client.set_poked(); 
} 

另一個解決方案是引入不需要self方法:

impl Server { 
    pub fn poke_client(&mut self, token: usize) { 
     let client = self.clients.get_mut(&token).unwrap(); 
     Server::poke(client); 
    } 

    fn poke(c: &mut Client) { 
     c.set_poked(); 
    } 
} 

您可以傳遞是需要的的self任何其他部件爲poke。這可能是引入介於ServerClient之間的新對象的好時機。

相關問題