Comment by antonvs
6 days ago
What OO features are you thinking of that Rust doesn't have?
Traits give you the ability to model typical GUI OO hierarchies, e.g.:
trait Widget {
fn layout(&mut self, constraints: Constraints);
fn paint(&self, ctx: &mut PaintCtx);
fn handle_event(&mut self, event: Event);
}
struct Button { ... }
struct Label { ... }
impl Widget for Button { ... }
impl Widget for Label { ... }
let mut widgets: Vec<Box<dyn Widget>> = Vec::new();
Implementation inheritance can be achieved with good old shared functions that take trait arguments, like this:
fn paint_if_visible<W>(widget: &W, ctx: &mut PaintCtx)
where
W: HasBounds + HasVisibility,
{
if widget.is_visible() {
ctx.paint_rect(widget.bounds());
}
}
You can also define default methods at the trait level.
This all ends up being much more precise, clear, and strongly typed than the typical OO inheritance model, while still following a similar overall structure.
You can see real world examples of this kind of thing in the various GUI toolkits for Rust, like Iced, gpui, egui, Dioxus, etc.
You can do OO this way if you really want in Rust, kinda like how you can do it in C, but it gets cumbersome. Especially because there's no GC.
But it's not "kinda how you can do it in C". Traits are a core feature of Rust, any non-trivial Rust program uses them. Traits alone give you polymorphism across disparate types, exactly as in OO - actually better than standard OO (without interfaces), because trait polymorphism works without requiring inheritance from a common ancestor.
> Especially because there's no GC.
This is the only real issue I can think of. However, for implementing something like a UI, automatic GC isn't really necessary because the lifetime of widgets etc. maps very well to the lexical/RAII model. Windows own widgets, etc. Again, see all the UI toolkits implemented in Rust.
I know the Rust trait system has an answer to every OO concept. Another is that data field inheritance is replaced by composition. But these are more workarounds for the rarer cases you want to do OO in Rust, not the intended usual path, and doing OOP this way will get tedious. Otherwise, there'd be no difference and everyone would call Rust an OO language.
Not so sure about not needing GC. Many times a problem seems easy without GC until you get into the weeds. Like why did ObjC feel the need to add ARC (not GC but similar goal)?
2 replies →