Given these two structs:
pub struct RectangleRenderer {
canvas: Canvas,
origin: Point,
shape: Rectangle,
}
pub struct CircleRenderer {
canvas: Canvas,
center: Point,
shape: Circle,
}
As I come from Java, I would extract a base class ShapeRenderer
out of those and apply the fields canvas
and origin
into that while the specific types will keep their field called shape
. What's the best practice in Rust for this situation since traits only act similar to interfaces and therefore do not allow properties/fields?
This looks like a perfect case for generics.
You can make a single struct like this:
Note that I have bounded the generic type
T
by a traitShape
(that you would have to create). You can put any bounds here you like (or no bounds at all), but you will be restricted to using members of those traits.Anything that you want to be able to access in your shapes would need to be exposed by
Shape
. For example, if you need the center and area, then the trait definition might look like this:If that is not enough flexibility, you could also give
ShapeRenderer
special behavior for only specific shapes. For example:Note that inside this
impl
, we have access to all the fields ofRectangle
, not just the functions inShape
.Alternatively, you could create a base struct and then include it as a member of your final structs:
This is the closest thing in Rust to standard inheritance.
Thirdly, if you only care about code duplication when creating these structs and don't want them to share anything but fields, you could use a macro:
While the generics example is the most complicated, it is also the most powerful and flexible. It lets you easily have code shared between your structs, while also letting you have code specific to one that gives you access to all its fields.