在struct impl

时间:2015-04-27 16:35:12

标签: hashmap rust borrow-checker

给出一个像这样的简单结构:

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>>, } ,这会让事情变得非常可怕:

clients

或者将RefCell包裹在Server中,这样就无法为pub fn client_by_token(&self, token: usize) -> Option<&Client> { self.clients_tok.get(&token) } 提供像这样的简单方法:

with_client_by_token(|c| ...)

强迫我使用闭包(例如Uncaught SyntaxError: Unexpected token ))。

1 个答案:

答案 0 :(得分:1)

正如错误消息所示,当它已被可变借用时,您无法重新借用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之间进行调解的新对象的好时机。