For my game rules engine, I have a central trait called Rule that handles game callbacks. There are two types of Rules: a BaseRule applies to any entity in the game, and a CreatureRule applies only to Creatures. I currently structure the code like this:
trait BaseRule<T> {
fn on_turn_start(&self, owner: &T) {}
}
#[typetag::serde(tag = "type")]
pub trait CreatureRule: BaseRule<Creature> {
fn on_death(&self, owner: &Creature) {}
}
This works fine, but is slightly annoying because you need to implement both Rule and CreatureRule for every implementation. I tried to make a blanket implementation of BaseRule:
impl<R: CreatureRule> BaseRule<Creature> for R {
}
but this introduces a conflict if I try to add a new implementation of the BaseRule trait, e.g. via
impl BaseRule<Creature> for BaseMeleeDamageAttack {
fn on_turn_start(&self, owner: &Creature) {
// do stuff
}
}
since there can't be two implementations of the same trait. Is there a way I can provide a blanket default implementation of BaseRule to types that implement CreatureRule but still allow them to override the default implementation of the functions?
(if possible I'd prefer to avoid having generic type parameters on CreatureRule since Serde serialization doesn't work for traits with generic types.)