简体   繁体   English

我如何通过Rc <RefCell<Box<MyStruct> &gt;&gt;接受Rc的功能 <RefCell<Box<dyn MyTrait> &gt;&gt;?

[英]How do I pass Rc<RefCell<Box<MyStruct>>> to a function accepting Rc<RefCell<Box<dyn MyTrait>>>?

I have originally asked this question here , but it was marked as duplicate, although it duplicates only a part of it in my opinion, so I have created a more specific one: 我最初在这里问了这个问题,但它被标记为重复,虽然它在我看来只复制了它的一部分,所以我创建了一个更具体的一个:

Consider the following code: 请考虑以下代码:

use std::rc::Rc;

trait MyTrait {
    fn trait_func(&self);
}

struct MyStruct1;

impl MyStruct1 {
    fn my_fn(&self) {
        // do something
    }
}

impl MyTrait for MyStruct1 {
    fn trait_func(&self) {
        // do something
    }
}

fn my_trait_fn(t: Rc<dyn MyTrait>) {
    t.trait_func();
}

fn main() {
    let my_str: Rc<MyStruct1> = Rc::new(MyStruct1);
    my_trait_fn(my_str.clone());
    my_str.my_fn();
}

This code works fine. 这段代码工作正常。 Now I want to change the definition of trait_func to accept a &mut self , but it won't work as Rc works with immutable data only. 现在我想更改trait_func的定义以接受&mut self ,但它不起作用,因为Rc仅适用于不可变数据。 The solution I use is to wrap MyTrait into RefCell : 我使用的解决方案是将MyTrait包装到RefCell

use std::cell::RefCell;

fn my_trait_fn(t: Rc<RefCell<Box<dyn MyTrait>>>) {
    t.borrow_mut().trait_func();
}

fn main() {
    let my_str: Rc<RefCell<Box<MyStruct1>>> = Rc::new(RefCell::new(Box::new(MyStruct1)));
    my_trait_fn(my_str.clone());
    my_str.my_fn();
}

When I compile it I get an error: 当我编译它时,我收到一个错误:

error[E0308]: mismatched types
  --> src/main.rs:27:17
   |
27 |     my_trait_fn(my_str.clone());
   |                 ^^^^^^^^^^^^^^ expected trait MyTrait, found struct `MyStruct1`
   |
   = note: expected type `std::rc::Rc<std::cell::RefCell<std::boxed::Box<dyn MyTrait + 'static>>>`
              found type `std::rc::Rc<std::cell::RefCell<std::boxed::Box<MyStruct1>>>`
   = help: here are some functions which might fulfill your needs:
           - .into_inner()

What's the best way to go around this problem? 解决这个问题的最佳方法是什么?

(An older revision of this answer essentially advised to clone the underlying struct and put it in a new Rc<RefCell<Box<MyTrait>> object; this was necessary at the time on stable Rust, but since not long after that time, Rc<RefCell<MyStruct>> will coerce to Rc<RefCell<MyTrait>> without trouble.) (这个答案的旧版本基本上建议克隆底层结构并将其放入一个新的Rc<RefCell<Box<MyTrait>>对象;这在稳定Rust的时候是必要的,但是在那之后不久, Rc<RefCell<MyStruct>>Rc<RefCell<MyStruct>>强制转到Rc<RefCell<MyTrait>> 。)

Drop the Box<> wrapping, and you can coerce Rc<RefCell<MyStruct>> to Rc<RefCell<MyTrait>> freely and easily. 放下Box<>包装,你可以轻松地将Rc<RefCell<MyTrait>>强制Rc<RefCell<MyStruct>>Rc<RefCell<MyTrait>> Recalling that cloning an Rc<T> just produces another Rc<T> , increasing the refcount by one, you can do something like this: 回想克隆一个Rc<T>只产生另一个Rc<T> ,将refcount增加一,你可以这样做:

use std::rc::Rc;
use std::cell::RefCell;

trait MyTrait {
    fn trait_func(&self);
}

#[derive(Clone)]
struct MyStruct1;
impl MyStruct1 {
    fn my_fn(&self) {
        // do something
    }
}

impl MyTrait for MyStruct1 {
    fn trait_func(&self) {
        // do something
    }
}

fn my_trait_fn(t: Rc<RefCell<MyTrait>>) {
    t.borrow_mut().trait_func();
}

fn main() {
    // (The type annotation is not necessary here, but helps explain it.
    // If the `my_str.borrow().my_fn()` line was missing, it would actually
    // be of type Rc<RefCell<MyTrait>> instead of Rc<RefCell<MyStruct1>>,
    // essentially doing the coercion one step earlier.)
    let my_str: Rc<RefCell<MyStruct1>> = Rc::new(RefCell::new(MyStruct1));
    my_trait_fn(my_str.clone());
    my_str.borrow().my_fn();
}

As a general rule, see if you can make things take the contained value by reference, ideally even generically— fn my_trait_fn<T: MyTrait>(t: &T) and similar, which can typically be called as my_str.borrow() with automatic referencing and dereferencing taking care of the rest—rather than the whole Rc<RefCell<MyTrait>> thing. 作为一般规则,看看你是否可以通过引用来获取所包含的值,理想情况下甚至通常是fn my_trait_fn<T: MyTrait>(t: &T)和类似的,通常可以自动调用my_str.borrow()参考和解除引用照顾其余的 - 而不是整个Rc<RefCell<MyTrait>>事情。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 向下转换 Rc <refcell<box<struct> &gt;&gt; 到 Rc <refcell<box<dyn trait> &gt;&gt; </refcell<box<dyn></refcell<box<struct> - Downcasting a Rc<RefCell<Box<struct>>> to Rc<RefCell<Box<dyn trait>>> 我如何施放 Rc <refcell<concretetype> &gt; 到 Rc <refcell<dyn trait> &gt;? </refcell<dyn></refcell<concretetype> - How do I cast Rc<RefCell<ConcreteType>> to Rc<RefCell<dyn Trait>>? 如何通过Rc <refcell<dyn t> > 想要 &dyn T 的 fn? </refcell<dyn> - How to pass Rc<RefCell<dyn T>> to fn that wants &dyn T? 如何移动 Vec <box<dyn trait> &gt; 走进 Vec <rc<refcell<dyn trait> &gt;&gt; </rc<refcell<dyn></box<dyn> - How to move a Vec<Box<dyn Trait>> Into Vec<Rc<RefCell<dyn Trait>>> Rc,RefCell和Box组合的新类型模式 - Newtype pattern of the combinations of Rc, RefCell and Box 如何获得一个盒子的`&amp;mut T` <rc<refcell<t> &gt;&gt;? </rc<refcell<t> - How to get `&mut T` of a Box<Rc<RefCell<T>>>? 如何向下转换 Rc <refcell<dyn io::write> > 变成一个具体的类型? </refcell<dyn> - How to downcast Rc<RefCell<dyn io::Write>> into a concrete type? 如何修改RC <RefCell> 从内部关闭? - How do I modify Rc<RefCell> from inside the closure? 你如何转换一个盒子<dyn trait>到 Rc<dyn trait> ?</dyn></dyn> - How do you convert a Box<dyn Trait> to a Rc<dyn Trait>? 将基于Box的树结构适配到Rc+RefCell时,如何处理“temporary value dropped”错误? - How to handle "temporary value dropped" error when adapting Box-based tree structure to Rc+RefCell?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM