如何将 Rc<RefCell<_>> 中的具体对象转换为动态特征对象? [复制]

Posted

技术标签:

【中文标题】如何将 Rc<RefCell<_>> 中的具体对象转换为动态特征对象? [复制]【英文标题】:How do I cast a concrete object in a Rc<RefCell<_>> to a dynamic trait object? [duplicate] 【发布时间】:2022-01-19 00:10:25 【问题描述】:

我有实现ModifyValue 特征的结构MyTextMyText::new 返回Rc&lt;RefCell&lt;MyText&gt;&gt;

我想要一个结构Modifier,给定Rc&lt;RefCell&lt;dyn ModifyValue&gt;&gt; 类型的喷射(实际上是任何实现特征ModifyValue 的动态对象),知道如何调用给定对象的modify 方法。

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

trait ModifyValue 
    fn modify(&mut self, s: &String);


struct MyText 
    value: String,


impl MyText 
    pub fn new() -> Rc<RefCell<Self>> 
        Rc::new(RefCell::new(MyText 
            value: String::from("Hello world"),
        ))
    


impl ModifyValue for MyText 
    fn modify(&mut self, s: &String) 
        self.value = s.clone();
    


struct Modifier 
    what: Rc<RefCell<dyn ModifyValue>>,


impl Modifier 
    pub fn new(el: &Rc<RefCell<dyn ModifyValue>>) -> Self 
        Modifier 
            what: Rc::clone(el),
        
    

    pub fn modify(&self, new_val: &String) 
        Rc::clone(&self.what).borrow_mut().modify(new_val);
    


fn main() 
    let txt = MyText::new();
    println!("", txt.borrow_mut().value);

    Rc::clone(&txt).borrow_mut().value = String::from("Bye Bye");
    println!("", txt.borrow_mut().value);

    Rc::clone(&txt)
        .borrow_mut()
        .modify(&String::from("Bye Bye, Hello world"));
    println!("", txt.borrow_mut().value);

    //// Problem here.
    let modifier = Modifier::new(&txt);
    /// Error .... !!!!!
    modifier.modify(&String::from("hola mundo"));
    //// ......

    println!("", txt.borrow_mut().value);

它给出了一个错误,我不能用它的特性动态地钩住对象txt。:

error[E0308]: mismatched types
  --> src/main.rs:55:34
   |
55 |     let modifier = Modifier::new(&txt);
   |                                  ^^^^ expected trait object `dyn ModifyValue`, found struct `MyText`
   |
   = note: expected reference `&Rc<RefCell<(dyn ModifyValue + 'static)>>`
              found reference `&Rc<RefCell<MyText>>`

如果我删除两个有问题的行,代码就可以工作。

在 C++ 中,我会使用纯虚拟类来执行此操作,但我无法在 Rust 中重现它(尤其是使用 Rc)。

【问题讨论】:

看来Clone an Rc<RefCell<MyType> trait object and cast it的答案可能会回答您的问题; How do I cast Rc<RefCell<ConcreteType>> to Rc<RefCell<dyn Trait>>? 。如果没有,请edit您的问题来解释差异。否则,我们可以将此问题标记为已回答。 【参考方案1】:

感谢这个话题的建议,我已经解决了:How do I cast Rc<RefCell<ConcreteType>> to Rc<RefCell<dyn Trait>>?

下面是我的解决方案:

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

trait ModifyValue 
    fn modify(&mut self, s: &String);


struct MyText 
    value: String,


impl MyText 
    pub fn new() -> Rc<RefCell<Self>> 
        Rc::new(RefCell::new(MyText 
            value: String::from("Hello world"),
        ))
    

impl ModifyValue for MyText 
    fn modify(&mut self, s: &String) 
        self.value = s.clone();
    


struct Modifier 
    what: Rc<RefCell<dyn ModifyValue>>,


impl Modifier 
    pub fn new(el: &Rc<RefCell<dyn ModifyValue>>) -> Self 
        Modifier 
            what: Rc::clone(el),
        
    

    pub fn modify(&self, new_val: &String) 
        Rc::clone(&self.what).borrow_mut().modify(new_val);
    


fn main() 
    let txt = MyText::new();
    println!("", txt.borrow_mut().value);

    Rc::clone(&txt).borrow_mut().value = String::from("Bye Bye");
    println!("", txt.borrow_mut().value);

    Rc::clone(&txt)
        .borrow_mut()
        .modify(&String::from("Bye Bye, Hello world"));
    println!("", txt.borrow_mut().value);

    
    let txt_c = txt.clone() as Rc<RefCell<dyn ModifyValue>>;
    let modifier = Modifier::new(&txt_c);
    modifier.modify(&String::from("hola mundo"));

    println!("", txt.borrow_mut().value);

【讨论】:

以上是关于如何将 Rc<RefCell<_>> 中的具体对象转换为动态特征对象? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

Rc<RefCell<T>> 和 RefCell<Rc<T>> 有啥区别?

Rc<RefCell<T>> 和 RefCell<Rc<T>> 有啥区别?

Rayon 如何防止线程之间使用 RefCell<T>、Cell<T> 和 Rc<T>?

使用 RefCell 和 Rc 处理循环图中的内存泄漏

是否有替代方法或方法让 Rc<RefCell<X>> 限制 X 的可变性?

一个模块中有 Rc<T>s,另一个模块中有 Rc<RefCell<T>>s 引用相同的数据