Rust trait state

I'll start with this monster "Monster" code from Rust for Rubyist:

trait Monster {
    fn attack(&self);
    fn new() -> Self;
}

struct IndustrialRaverMonkey {
    life: int,
    strength: int,
    charisma: int,
    weapon: int,
}

struct DwarvenAngel {
    life: int,
    strength: int,
    charisma: int,
    weapon: int,
} ...
impl Monster for IndustrialRaverMonkey { ...
impl Monster for DwarvenAngel { ...

I worry about duplication of code. In Java I would create interface that define attack method and base class with all that parameters (life, strength, charisma, weapon). I will do same thing in C++ with abstract class. I can find some ugly and unintuitive ways to work around this problem, but is there a good way to reduce code? I mean, to keep it scalable and readable.

Answers


Another approach, which favors composition, and from which is easier to diverge implementations if needed (e.g., the Characteristics for DwarvenAngel require an additional field):

trait Monster {
    fn attack(&self);
}

struct Characteristics {
    life: int,
    strength: int,
    charisma: int,
    weapon: int,
}

struct IndustrialRaverMonkey {
    characteristics: Characteristics
}

struct DwarvenAngel {
    characteristics: Characteristics
}

fn same_attack(c: Characteristics) {
    fail!("not implemented")
}

impl Monster for IndustrialRaverMonkey {
    fn attack(&self) {
        same_attack(self.characteristics)
    }
}

impl Monster for DwarvenAngel {
    fn attack(&self) {
        same_attack(self.characteristics)
    }
}

Or, you can have an enum represent your monster types, very similar to A.B.'s answer:

trait Monster {
    fn attack(&self);
}

struct Characteristics {
    life: int,
    strength: int,
    charisma: int,
    weapon: int,
}

enum Monsters {
    IndustrialRaverMonkey(Characteristics),
    DwarvenAngel(Characteristics),
}

fn same_attack(_: &Characteristics) {
    fail!("not implemented")
}

impl Monster for Monsters {
    fn attack(&self) {
        match *self {
            IndustrialRaverMonkey(ref c) => same_attack(c),
            DwarvenAngel(ref c)          => same_attack(c)
        }
    }
}

Would you consider something like this an acceptable solution?

trait Actor {
    fn attack(&self);
}

enum MonsterId {
    IndustrialRaverMonkey,
    DwarvenAngel
}

struct Monster {
    life: int,
    strength: int
}

impl Monster {
    fn new(id: MonsterId) -> Monster {
        match id {
            IndustrialRaverMonkey => 
            Monster { life: 12, strength: 8 },

            DwarvenAngel => 
            Monster { life: 18, strength: 12 }
        }
    }
}


impl Actor for Monster { 
    fn attack(&self) {}
}

Updated with a better example.


Need Your Help

Difference between: <T> ReturnContainer test() and: <T> ReturnContainer<T> test()?

java generics

What is the difference between the signatures of the two methods below?

PHP to mySQL check if user exists

php mysql authentication user-controls

I have a script that updates/creates user from an iOS device. Now i want to have the script also check if the user already exists in the database. I am going to restrict this to username for now, s...