Enums in rust is quite powerful we can attached method to it,

but we cannot change the enums method for each variants

see idiomatic enum code:

enum Animal {
    Mammal,
    Fish,
    Bird,
}

impl Animal {
    fn walk(&self) {
        match self {
            Animal::Mammal => println!("Mammal walks"),
            Animal::Fish => println!("Fish dont walk"),
            Animal::Bird => println!("Bird can walk"),
        }
    }

    fn fly(&self) {
        match self {
            Animal::Mammal => println!("Mammal dont fly"),
            Animal::Fish => println!("Fish dont fly"),
            Animal::Bird => println!("Bird can fly"),
        }
    }

    fn swim(&self) {
        match self {
            Animal::Mammal => println!("Mammal can swim"),
            Animal::Fish => println!("Fish can swim"),
            Animal::Bird => println!("Bird dont swim"),
        }
    }
}

fn main() {
    let mammal = Animal::Mammal;
    mammal.fly();
    mammal.walk();
    mammal.swim();
}

But that doesn’t make sense for a fish to have the abilities to play or walk.

We can do it with structs and trait , this is very simple , and call it a day


pub trait Animal {
     fn eat(&self);
}

pub trait Mammal: Animal {
    fn walk(&self);
}

pub trait Aquatic: Animal {
    fn swim(&self);
}

pub trait Aerial: Animal {
    fn fly(&self);
}

pub struct Human;
pub struct Dolphin;

pub struct Bat;

impl Animal for Human {
     fn eat(&self) {
        println!("The human is eating.");
    }
}

impl Mammal for Human {
    fn walk(&self) {
        println!("The human is walking.");
    }
}

impl Animal for Dolphin {
    fn eat(&self) {
        println!("The dolphin is eating.");
    }
}

impl Aquatic for Dolphin {
    fn swim(&self) {
        println!("The dolphin is swimming.");
    }
}

impl Animal for Bat {
    fn eat(&self) {
        println!("The bat is eating.");
    }
}

impl Aerial for Bat {
    fn fly(&self) {
        println!("The bat is flying.");
    }
}

fn main() {
     
    let human = Human {};
    human.eat();
    human.walk();

    let dolphin = Dolphin {};
    dolphin.eat();
    dolphin.swim();

    let bat = Bat {};
    bat.eat();
    bat.fly();
}

but we want enums to have that same behavior

Luckily for us , we can use Type State pattern in Rust.

Not only we have that same behavior but now we can also morph from one variants to another

RUN the example code on Rust Playground: