-1

I have the struct MyText which implements the ModifyValue trait. MyText::new returns Rc<RefCell<MyText>>.

I want a struct Modifier that, given a jet of type Rc<RefCell<dyn ModifyValue>> (practically any dynamic object that implements the trait ModifyValue), knows how to call the modify method of the given object.

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

It gives an error and I can't dynamically hook the object txt with its trait.:

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>>`

If I remove the two problematic lines the code works.

In C++ I would do this with a pure virtual class, but I can't reproduce it in Rust (especially using Rc).

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Giggi
  • 681
  • 2
  • 9
  • 17
  • 2
    It looks like your question might be answered by the answers of [Clone an Rc trait object and cast it](https://stackoverflow.com/q/55959384/155423); [How do I cast Rc> to Rc>?](https://stackoverflow.com/q/65495270/155423) . If not, please **[edit]** your question to explain the differences. Otherwise, we can mark this question as already answered. – Shepmaster Dec 15 '21 at 21:09

1 Answers1

1

I have solved thanks to the suggestion from this topic: How do I cast Rc<RefCell<ConcreteType>> to Rc<RefCell<dyn Trait>>?

Below my solution:

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);
}
Jmb
  • 18,893
  • 2
  • 28
  • 55
Giggi
  • 681
  • 2
  • 9
  • 17