在 struct impl 中访问 hashmap 字段值作为 &mut
Accessing hashmap field value as &mut inside struct impl
给定一个像这样的简单结构:
struct Server {
clients: HashMap<usize, Client>
}
作为 &mut
访问 Client
的最佳方式是什么?考虑以下代码:
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);
}
我看到的仅有的两个选项是在 Client 中使用 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| ...)
)。
正如错误消息所说,当它已经被可变借用时,你不能重新借用 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
所需的任何其他部分。现在可能是引入一个介于 Server
和 Client
之间的新对象的好时机。
给定一个像这样的简单结构:
struct Server {
clients: HashMap<usize, Client>
}
作为 &mut
访问 Client
的最佳方式是什么?考虑以下代码:
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);
}
我看到的仅有的两个选项是在 Client 中使用 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| ...)
)。
正如错误消息所说,当它已经被可变借用时,你不能重新借用 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
所需的任何其他部分。现在可能是引入一个介于 Server
和 Client
之间的新对象的好时机。