Hello everyone! I recently joined the Rustacean club and I'm really excited to learn Rust. Currently I'm still trying to understand some of its intricacies.
I'm currently trying to understand a Rust way of doing something similar to the OOP equivalent of "abstract function" implementation in the context of Win32 GUI drawing by using Trait objects.
I've already gone through Using Trait Objects That Allow for Values of Different Types - The Rust Programming Language, but in my case I don't think it's possible for me to move the ownership of my_wnd: MyWindow
into the Window
itself, but maybe I'm wrong. So here I am asking for your help with the lifetime fun!
So I'm having some trouble solving this reference lifetime issue, and this is the problematic line: my_wnd.window.set_painter(&my_wnd);
I tried experimenting with Box
ed types too and I'm pretty sure there's probably a way of avoiding or solving this problem, but I'm not sure how to solve this.
Here's a rough idea of what I'm trying to do:
// window.rs
const WM_PAINT: u32 = 15u32;
trait Paintable {
fn paint(&self) -> ();
}
struct Window {
// Using 'static only to avoid using lifetime generics to keep the example simple enough
painter: Option<&'static dyn Paintable>,
}
impl Window {
fn message_handler(&mut self, message: u32) {
match message {
WM_PAINT => { self.paint(); },
_ => {}
}
}
fn set_painter(&mut self, painter: &'static impl Paintable) {
self.painter = Some(painter);
}
fn paint(&self) {
if let Some(painter) = self.painter {
painter.paint();
} else {
println!("Painter not implemented");
}
}
}
// my-window.rs
struct MyWindow {
window: Window,
data: u32,
}
impl MyWindow {
fn new() -> Self {
let mut my_wnd = Self {
window: Window { painter: None },
data: 42,
};
// I need to tell Window to use MyWindow impl for Paintable
// This is obviously WRONG, but you get the idea!
my_wnd.window.set_painter(&my_wnd);
my_wnd
}
}
impl Paintable for MyWindow {
fn paint(&self) {
println!("Hello MyWindow with data {}", self.data);
}
}
fn main() {
let mut my_wnd = MyWindow::new();
// This is triggered from some other place
my_wnd.window.message_handler(WM_PAINT);
// I want to tell MyWindow to use its paint() when Window makes a paint, and
// that would result in the following output: "Hello MyWindow with data 42"
}
Error detail:
error[E0502]: cannot borrow `my_wnd.window` as mutable because it is also borrowed as immutable
--> src/main.rs:50:9