如何传递Rc< RefCell< Box< MyStruct>>>接受Rc< RefCell< Box< dyn MyTrait>>>的函数? [英] How do I pass Rc<RefCell<Box<MyStruct>>> to a function accepting Rc<RefCell<Box<dyn MyTrait>>>?

查看:149
本文介绍了如何传递Rc< RefCell< Box< MyStruct>>>接受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:

考虑以下代码:

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();
}

此代码可以正常工作.现在,我想更改trait_func的定义以接受&mut self,但是它将不起作用,因为Rc仅适用于不可变数据.我使用的解决方案是将MyTrait包装到RefCell中:

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. The solution I use is to wrap MyTrait into 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();
}

编译时出现错误:

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?

推荐答案

(该答案的旧版本实质上建议克隆底层结构并将其放入新的Rc<RefCell<Box<MyTrait>>对象中;这在时间稳定在Rust上,但由于在此之后不久,Rc<RefCell<MyStruct>>会强制转换为Rc<RefCell<MyTrait>>而没有麻烦.)

(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.)

拖放Box<>包装,您可以轻松轻松地将Rc<RefCell<MyStruct>>强制为Rc<RefCell<MyTrait>>.回顾克隆Rc<T>只会产生另一个Rc<T>,将引用计数增加1,您可以执行以下操作:

Drop the Box<> wrapping, and you can coerce Rc<RefCell<MyStruct>> to Rc<RefCell<MyTrait>> freely and easily. Recalling that cloning an Rc<T> just produces another Rc<T>, increasing the refcount by one, you can do something like this:

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();
}

作为一般规则,请查看是否可以使事物通过引用来获取包含的值,理想情况下甚至可以泛泛地引用fn my_trait_fn<T: MyTrait>(t: &T)或类似内容,通常可以将其称为my_str.borrow(),并自动进行引用和取消引用,并照顾其余部分—而不是整个Rc<RefCell<MyTrait>>事情.

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.

这篇关于如何传递Rc&lt; RefCell&lt; Box&lt; MyStruct&gt;&gt;&gt;接受Rc&lt; RefCell&lt; Box&lt; dyn MyTrait&gt;&gt;&gt;的函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆