将RefCell和Rc包装为结构类型

时间:2018-09-07 14:53:59

标签: syntax rust traits type-bounds

我想拥有一个具有可写字段但可显式借用的结构:

<android.support.design.widget.BottomNavigationView
    android:id="@+id/bottomNavigationView2"
    android:layout_width="0dp"
    android:layout_height="77dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintHorizontal_bias="0.0"
    app:layout_constraintStart_toStartOf="parent"
    app:menu="@menu/links_nav">

...因此它可以在内部使用它:

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 stdinstdout传递给stderr结构。在App中,这些将是真实的stdin / stdout / stderr。在测试中,这些可能是游标。由于我需要在fn main之外访问它们(例如在测试中),因此我需要多个所有者(因此App)和运行时可变借用(因此Rc)。

我该如何实现?

1 个答案:

答案 0 :(得分:2)

这不是将多个约束应用于类型参数的方式。而是使用+运算符,例如:<W: Clone + Write + BorrowMut>

但是,如果您希望BorrowMutRefCell的抽象,那么它将不起作用。 borrow_mut的{​​{1}}方法不是任何特征的一部分,因此您将需要直接在数据结构中依赖RefCell

RefCell

话虽如此,但最好的做法是不对结构施加不必要的约束。您实际上可以将其保留在此处,稍后在struct App<W: Clone + Write> { stdout: Rc<RefCell<W>>, } 上提及它们。

impl

为了访问struct App<W> { stdout: Rc<RefCell<W>>, } 的内容,您需要用Rc取消引用。在您的情况下,这可能会有些棘手,因为*中有一个覆盖的impl,这意味着BorrowMut具有一个不同 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); 已被克隆到光标中。否则它将被移动,您以后将无法再使用。