Reputation: 3012
While porting an application from Python to Rust I ran into this problem.
If we have classes like this:
class Backend:
def __init__(self, result_consumer=None):
self.result_consumer = ResultConsumer(self, ..)
class ResultConsumer:
def __init__(self, backend=None):
self.backend=backend
and ResultConsumer is regularly calling methods like self.backend.method()
and Backend is also calling methods like self.result_consumer.method()
.
In Rust you can't just use struct fields to establish such a relationship.
I tried an approach with generics (as ResultConsumer should support multiple backends)
struct ResultConsumer<B: Backend> {
backend: Arc<B>,
}
struct Backend {
result_consumer: ResultConsumer<Self>
}
what would be the most idiomatic way to represent this relationship in Rust? Is my example approach viable?
I am asking specifically, because while it compiles I cannot figure out how to populate the ResultConsumer
in the result_consumer
field for Backend
when I construct it.
Upvotes: 1
Views: 240
Reputation: 7100
If I understand you well, you can use something like the following
struct ResultConsumer {
backend: RefCell<Weak<Backend>>,
}
struct Backend {
result_consumer: RefCell<Rc<ResultConsumer>>,
}
impl Backend {
fn new() -> Rc<Backend> {
println!("Backend::new");
let mut b_rc = Rc::new(Backend {
result_consumer: RefCell::new(Rc::new(ResultConsumer {
backend: RefCell::new(Weak::new()),
})),
});
*b_rc.result_consumer.borrow().backend.borrow_mut() = Rc::downgrade(&b_rc);
b_rc
}
}
Upvotes: 1