Consider the following dumbed-down example:
pub trait ThemePark<A, V>
where
A: Attraction,
V: Visitor,
{
fn create(square_size: u32, name: &str) -> Self;
fn get_attractions(&self) -> Vec<A>;
fn get_visitors(&self) -> Vec<V>;
}
pub trait Attraction {}
pub trait Visitor {}
A concrete ThemePark
could have an arbitrary set of attractions, as well as visitors. They are implemented with structs:
struct ElderlyWhiteMale;
impl Visitor for ElderlyWhiteMale {}
A ThemePark
is wrapped in some company's assets, like so:
pub struct Asset<'a> {
name: &str,
theme_park: Box<ThemePark<> + 'a> // <-- This won't compile, as ThemePark needs 2 type arguments
}
This begins my pain. I put ThemePark
in a Box
because I don't know the size of it at compile time. It could be wrapped around any kind of Attraction
and Visitor
.
ThemePark
needs 2 type arguments, but I can't know them at compile-time. Somewhere in my code I read this from an external file and build a ThemePark
accordingly.
The idea is, that at runtime I can create a ThemePark
from an external source and then invoke the functions
defined in the trait on it.
impl Asset {
fn init_and_query() -> () {
let theme_park: Box<ThemePark> = match external_file.get_theme_park_type {
ThemeParkType::FUN => unimplemented! {"There is no fun, yet!"},
ThemeParkType::SERIOUS => {
println!("Creating serious themepark");
SeriousThemePark::create(size /*...*/)
}
};
let attractions = theme_park.get_attractions();
// ... Do something with the attractions
}
}
pub enum ThemeParkType {
FUN,
SERIOUS,
}
I understand that I can't put the ThemePark
as-is on the stack... it's size is unknown at compile time, so the compiler can't know what to allocate.
That's why I either use a reference &
or wrap it in a Box
like I do here.
I understand there is type erasure, meaning that I would get back only a ThemePark
and not a SeriousThemePark
, but that would suffice for the moment.
Am I using traits all wrong here? How would you go and fix that. Coming from Java/Scala/C++ I seem to be stuck too deep in existing thinking.