Trait objects with associate types: what is the way to go?


#1

I have this idea, how to make it work? :slight_smile:

pub trait Entity {
}

pub trait EntityHandler<Entity> {
}

pub trait EntityPlugin {
    type Entity: Entity;
    type EntityHandler: EntityHandler<Self::Entity>;
}

lazy_static! {
    pub static ref PLUGINS: BTreeMap<String, Box<EntityPlugin>> ...
}

// -- cut here

struct PluginEntity {
    ...
}

struct PluginEntityHandler<PluginEntity> {
    ...
}

impl Entity for PluginEntity {
    ...
}

impl EntityHandler<P> for PluginEntityHandler where P: PluginEntity {
    ...
}

PLUGINS.insert("plugin1", Box<EntityPlugin<Entity=PluginEntity, EntityHandler=PluginEntityHandler>

#2

There’s a fundamental issue with this design. The issue is that it’s not possible to create the BTreeMap<String, Box<EntityPlugin>> type because the associated types Entity and EntityHandler still need to be specified. See this playground: https://is.gd/c4hCr6

Associated types don’t save you from having to specify their values, the difference between using associated types and generics in your case is that for a single implementation of EntityPlugin you can only have a single possible Entity and EntityHandler. So the difference is in the type implementation, rather than the type definition.

You can get around this issue by replacing the generics with methods that return a Box instead. Take this example: https://is.gd/tiOl5x

If you describe what you’re trying to achieve we can probably help a bit more :slight_smile:


#3

Thank you, @KodrAus, I will have a look: after asking the question I was looking at the actual Entity implementation :slight_smile: