How do I choose between using structs, enums, and traits when modeling data and behavior in Rust?
So at the very high level...
A struct is a collection of data that typically represents something:
#![allow(unused)] fn main() { struct Drink { brand: String, size: i32, } }
An enum represents a possible set of things:
#![allow(unused)] fn main() { enum DrinkType { Coffee, Soda, Water } }
Where enums get fun is that they can also carry data (like a tagged union from C, or a variant from C++):
#![allow(unused)] fn main() { enum DrinkType { Coffee { roast: CoffeeRoast }, Soda { brand: Brand }, Water } }
This really shines when you want to only store things that are possible - make impossible things unrepresentable.
Either of these can use impl to define functions. Adding a trait applies an interface to them - so now you can represent the type as a trait, and know that certain methods are available without knowing the concrete type.
So:
- Typically a
structis the right place if an entry is going to have all (or most) of the same fields. - An
enumis the right choice if you want to restrict to a valid type. - A
traitextends these to offer something. For example, theDisplaytrait makes them all work withformat!without having to write aformatfor all of them. You can also use traits for dynamic dispatch if you need single layer polymorphism.