Is there a nice way to avoid having to "use Trait" in end-user app

I'm basically looking at using How to implement inheritance-like feature for Rust? idea. I have a Shape struct and want an ElevationMap to do everything Shape does but with a few more properties and methods. Previously I had a macro that did it all fine but thought it would be nice to test out the inheritance-like-feature, and it does work, and is better in lots of ways... Except that any application using ElevationMap has to have an extra line at the beginning:

use pi3d::shape::AsMutShape;
...
    let mut terrain = pi3d::elevation_map::new();
    ...
    terrain.draw()

Which will seem like a magic incantation to anyone using the module. Better IMO to just make the shape property public

    ...
    let mut terrain = pi3d::elevation_map::new();
    ...
    terrain.shape.draw(); 

Is there any way to avoid this?

You could create an inherent method that just passes the implementation on to the trait. IMO it's not a big deal to have to import a trait, though.

2 Likes

OK, so the message is: You can do inheritance like features in rust using traits but it's actually better not to (for the time being maybe)!

I've stripped all the macro stuff out and all the AsMutShape trait stuff out and simply have the parent struct as an attribute of the child struct. Nice and simple.

It'll feel like you're trying to shove a square peg into a round hole. Just like you can kinda implement inheritance in C (e.g. COM and GObject) or procedural code in Haskell (do notation), but it'll feel very unnatural, require loads of boilerplate, and have lots of rough edges.

Rust is a turing-complete language, so it can create all the same constructs another language's compiler can. That said, different languages prefer different paradigms and will guide you to write code in a certain way. You may want to try a different approach instead of implementing a poor-man's inheritance. Rust has a lot to offer.


To answer the original question... If you have several traits that you'd like to be accessible you can create a prelude module that re-exports the traits. That way you just need to write use my_crate::prelude::* at the top of the file and it'll bring all your traits into scope.

1 Like

@Michael-F-Bryan ah yes prelude::* I know I'm making some contortions because of the way I started this project but it did seem like the method suggested by @ExpHP might be useful.

A couple of years ago I decided to learn Rust (and possibly provided a useful resource) by translating a python graphics module (pi3d) that I maintain. I kept the structures similar partly to see what the differences are and because I could actually, amazingly, copy a lot of the python and just {;} it. (Obviously there were major issues with borrowing and lifetimes but it was a salutary lesson)

As I say above, my original setup was to have a macro but I was rather unhappy about that. However after looking at the inheritance like trait idea I've come to the conclusion that it's much better to "simply" have a Shape struct as a component of the ElevationMap struct and not hide it behind an AsMutShape trait.

1 Like