首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何将Rc<RefCell<Box<MyStruct>>>传递给接受Rc<RefCell<Box<dyn MyTrait>>>的函数?

如何将Rc<RefCell<Box<MyStruct>>>传递给接受Rc<RefCell<Box<dyn MyTrait>>>的函数?
EN

Stack Overflow用户
提问于 2015-06-16 07:26:29
回答 1查看 3.1K关注 0票数 8

我最初问过这个问题here,但它被标记为重复,虽然它只复制了其中的一部分,所以我创建了一个更具体的问题:

考虑以下代码:

代码语言:javascript
复制
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中。

代码语言:javascript
复制
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();
}

当我编译它时,我会得到一个错误:

代码语言:javascript
复制
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()

解决这个问题最好的方法是什么?

EN

回答 1

Stack Overflow用户

发布于 2015-06-16 07:55:55

(这个答案的旧版本基本上建议克隆底层结构,并将其放入一个新的Rc<RefCell<Box<MyTrait>>对象中;这在稳定锈蚀的时候是必要的,但不久之后,Rc<RefCell<MyStruct>>将毫不费力地胁迫Rc<RefCell<MyTrait>>。)

放下Box<>包装,您可以自由和轻松地胁迫Rc<RefCell<MyStruct>>Rc<RefCell<MyTrait>>。回顾一下,克隆Rc<T>只会产生另一个Rc<T>,从而使回溯数增加一个,您可以这样做:

代码语言:javascript
复制
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>>

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30861295

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档