在结构类型中包装 RefCell 和 Rc
Wrapping RefCell and Rc in a struct type
我想要一个具有可写字段但明确可借用的结构:
struct App<W: Clone<BorrowMut<Write>>> {
stdout: W,
}
...所以它可以在内部使用它:
impl<W: Clone<BorrowMut<Write>>> App<W> {
fn hello(&mut self) -> Result<()> {
Rc::clone(&self.stdout).borrow_mut().write(b"world\n")?;
Ok(())
}
}
我试着给它传递一个游标然后使用它:
let mut cursor = Rc::new(RefCell::new(Cursor::new(vec![0])));
let mut app = App { stdout: cursor };
app.hello().expect("failed to write");
let mut line = String::new();
Rc::clone(&cursor).borrow_mut().read_line(&mut line).unwrap();
锈皮:
error[E0107]: wrong number of type arguments: expected 0, found 1
--> src/bin/play.rs:6:21
|
6 | struct App<W: Clone<BorrowMut<Write>>> {
| ^^^^^^^^^^^^^^^^ unexpected type argument
我的最终目标:将 stdin
、stdout
和 stderr
传递给 App
结构。在 fn main
中,这些将是真实的 stdin/stdout/stderr。在测试中,这些可能是游标。由于我需要在 App
之外访问这些(例如在测试中),我需要多个所有者(因此 Rc
)和运行时可变借用(因此 RefCount
)。
我该如何实现?
这不是将多个约束应用于类型参数的方式。相反,您使用 +
运算符,如下所示:<W: Clone + Write + BorrowMut>
但是,如果您希望 BorrowMut
成为 RefCell
的抽象,那是行不通的。 RefCell
的 borrow_mut
方法不是任何特征的一部分,因此您需要直接在数据结构中依赖 RefCell
:
struct App<W: Clone + Write> {
stdout: Rc<RefCell<W>>,
}
话虽如此,但最好不要对结构施加不必要的约束。实际上,您可以将它们放在此处,稍后在 impl
中提及它们即可。
struct App<W> {
stdout: Rc<RefCell<W>>,
}
为了访问 Rc
的内容,您需要使用 *
取消引用。这在你的情况下可能有点棘手,因为有 BorrowMut
的毯子 impl
,这意味着 Rc
有 不同的 borrow_mut
,你绝对不想要。
impl<W: Clone + Write> App<W> {
fn hello(&mut self) -> Result<()> {
(*self.stdout).borrow_mut().write(b"world\n")?;
Ok(())
}
}
同样,当你使用它时,你需要取消引用 Rc
:
let cursor = Rc::new(RefCell::new(Cursor::new(vec![0])));
let mut app = App { stdout: cursor.clone() };
app.hello().expect("failed to write");
let mut line = String::new();
let mut cursor = (&*cursor).borrow_mut();
// move to the beginning or else there's nothing to read
cursor.set_position(0);
cursor.read_line(&mut line).unwrap();
println!("result = {:?}", line);
另外,请注意 Rc
已克隆到游标中。否则它会被移动,你以后不能再使用它。
我想要一个具有可写字段但明确可借用的结构:
struct App<W: Clone<BorrowMut<Write>>> {
stdout: W,
}
...所以它可以在内部使用它:
impl<W: Clone<BorrowMut<Write>>> App<W> {
fn hello(&mut self) -> Result<()> {
Rc::clone(&self.stdout).borrow_mut().write(b"world\n")?;
Ok(())
}
}
我试着给它传递一个游标然后使用它:
let mut cursor = Rc::new(RefCell::new(Cursor::new(vec![0])));
let mut app = App { stdout: cursor };
app.hello().expect("failed to write");
let mut line = String::new();
Rc::clone(&cursor).borrow_mut().read_line(&mut line).unwrap();
锈皮:
error[E0107]: wrong number of type arguments: expected 0, found 1
--> src/bin/play.rs:6:21
|
6 | struct App<W: Clone<BorrowMut<Write>>> {
| ^^^^^^^^^^^^^^^^ unexpected type argument
我的最终目标:将 stdin
、stdout
和 stderr
传递给 App
结构。在 fn main
中,这些将是真实的 stdin/stdout/stderr。在测试中,这些可能是游标。由于我需要在 App
之外访问这些(例如在测试中),我需要多个所有者(因此 Rc
)和运行时可变借用(因此 RefCount
)。
我该如何实现?
这不是将多个约束应用于类型参数的方式。相反,您使用 +
运算符,如下所示:<W: Clone + Write + BorrowMut>
但是,如果您希望 BorrowMut
成为 RefCell
的抽象,那是行不通的。 RefCell
的 borrow_mut
方法不是任何特征的一部分,因此您需要直接在数据结构中依赖 RefCell
:
struct App<W: Clone + Write> {
stdout: Rc<RefCell<W>>,
}
话虽如此,但最好不要对结构施加不必要的约束。实际上,您可以将它们放在此处,稍后在 impl
中提及它们即可。
struct App<W> {
stdout: Rc<RefCell<W>>,
}
为了访问 Rc
的内容,您需要使用 *
取消引用。这在你的情况下可能有点棘手,因为有 BorrowMut
的毯子 impl
,这意味着 Rc
有 不同的 borrow_mut
,你绝对不想要。
impl<W: Clone + Write> App<W> {
fn hello(&mut self) -> Result<()> {
(*self.stdout).borrow_mut().write(b"world\n")?;
Ok(())
}
}
同样,当你使用它时,你需要取消引用 Rc
:
let cursor = Rc::new(RefCell::new(Cursor::new(vec![0])));
let mut app = App { stdout: cursor.clone() };
app.hello().expect("failed to write");
let mut line = String::new();
let mut cursor = (&*cursor).borrow_mut();
// move to the beginning or else there's nothing to read
cursor.set_position(0);
cursor.read_line(&mut line).unwrap();
println!("result = {:?}", line);
另外,请注意 Rc
已克隆到游标中。否则它会被移动,你以后不能再使用它。