5

I have the following implementation, but I don't want to repeat myself. How can I use a implementation that have the same body on different structs without repeating?

impl Message for CreateHero {
    type Result = Result<Hero, Error>;
}

impl Message for SearchHero {
    type Result = Result<Hero, Error>;
}

impl Message for DeleteHero {
    type Result = Result<Hero, Error>;
}
KadoBOT
  • 2,944
  • 4
  • 16
  • 34
  • What is `Message`? Is it a trait of yours or a third party's? – rodrigo Aug 25 '18 at 14:16
  • Third party, from actix: https://docs.rs/actix/0.7.3/actix/trait.Message.html – KadoBOT Aug 25 '18 at 14:22
  • [The `duplicate` crate](https://crates.io/crates/duplicate) provides an attribute macro to solve exactly this. See also [my answer](https://stackoverflow.com/a/61467564/8171453) to the linked duplicate question for an example. – Emoun Apr 28 '20 at 08:23

1 Answers1

7

The answer to how to avoid repetition in Rust is usually macros.

Your case is actually quite simple, as macros go:

macro_rules! hero_message {
    ($name : ident) => {
        impl Message for $name {
            type Result = Result<Hero, Error>;
        }
    }
}
hero_message!{CreateHero}
hero_message!{SearchHero}
hero_message!{DeleteHero}

Reading the answer in the linked duplicated question, you can also write a generic trait implementation, that for simple problems like yours, would look more idiomatic. It would look like this:

trait MessageHero {}

impl<T: MessageHero> Message for T {
    type Result = Result<Hero, Error>;
}

impl MessageHero for CreateHero {}
impl MessageHero for SearchHero {}
impl MessageHero for DeleteHero {}
rodrigo
  • 94,151
  • 12
  • 143
  • 190