Skip to content

Instantly share code, notes, and snippets.

@aboglioli
Created July 17, 2020 09:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aboglioli/785f28776826719fa587cc78accda5c9 to your computer and use it in GitHub Desktop.
Save aboglioli/785f28776826719fa587cc78accda5c9 to your computer and use it in GitHub Desktop.
Change implementation of trait object using RefCell<Rc<dyn Obj>>
use std::rc::Rc;
use std::cell::RefCell;
// Databases
trait DB {
fn find(&self) -> String;
}
struct SQL;
impl DB for SQL {
fn find(&self) -> String {
"SQL".to_owned()
}
}
struct Mongo;
impl DB for Mongo {
fn find(&self) -> String {
"Mongo".to_owned()
}
}
// Services
trait Executor {
fn execute(&self);
}
struct Serv1 {
db: RefCell<Rc<dyn DB>>,
}
impl Serv1 {
fn change_db(&self, db: Rc<dyn DB>) {
*self.db.borrow_mut() = db;
}
}
impl Executor for Serv1 {
fn execute(&self) {
println!("Serv1: {}", self.db.borrow().find());
}
}
struct Serv2 {
db: Rc<dyn DB>,
serv1: Rc<Serv1>,
}
impl Executor for Serv2 {
fn execute(&self) {
println!("Serv2: {}", self.db.find());
self.serv1.execute();
}
}
struct Serv3 {
db: Rc<dyn DB>,
serv1: Rc<Serv1>,
serv2: Rc<Serv2>,
}
impl Executor for Serv3 {
fn execute(&self) {
println!("Serv3: {}", self.db.find());
self.serv1.execute();
self.serv2.execute();
}
}
fn main() {
let mongo: Rc<dyn DB> = Rc::new(Mongo);
let sql: Rc<dyn DB> = Rc::new(SQL);
let mut serv1 = Rc::new(Serv1 {
db: RefCell::new(Rc::clone(&sql)),
});
let serv2 = Rc::new(Serv2 {
db: Rc::clone(&mongo),
serv1: Rc::clone(&serv1),
});
let serv3 = Rc::new(Serv3 {
db: Rc::clone(&sql),
serv1: Rc::clone(&serv1),
serv2: Rc::clone(&serv2),
});
println!("#sql: {} | #mongo: {}", Rc::strong_count(&sql), Rc::strong_count(&mongo));
serv3.execute();
serv1.change_db(Rc::clone(&mongo));
println!("---");
println!("#sql: {} | #mongo: {}", Rc::strong_count(&sql), Rc::strong_count(&mongo));
serv3.execute();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment