Exhausting Exhaustive Matching Enum
I got two structs (`Dog` and `Cat`) which implements the same trait `Animal`.
#![allow(unused)]
pub struct Dog;
pub struct Cat;
trait Animal {
fn walk();
}
impl Animal for Dog {
fn walk() {
println!("Dog walking.");
}
}
impl Animal for Cat {
fn walk() {
println!("Cat walking.");
}
}
Then I have this function, which accepts a generic T type as a parameter. The generic type should implement the trait Animal and execute the method from the specified struct.
fn walk_module(animal: T) {
T::walk();
}
I hope to use this like so.
fn main() {
walk_module(Cat); // prints Cat walking.
}
So everything is good, the animal is walking.
Playground here: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=7c16dfbf651b0b5871e771e7b64d17fb
However, the issue starts when I try to fetch the structs from an enum.
-- snips --
enum AnimalCategory {
Dog(Dog),
Cat(Cat)
}
fn get_the_animal(category: &str) -> AnimalCategory {
match category {
"dog" => AnimalCategory::Dog(Dog),
"cat" => AnimalCategory::Cat(Cat),
_ => AnimalCategory::Dog(Dog),
}
}
fn main() {
// Option 1
let animal = get_the_animal("dog");
walk_module(animal); // this errors now because enum AnimalCategory does not implement the Animal trait, and so the animal can't walk
}
I do not want to implement the Animal trait for Animal category, but I know that I could implement methods for the enum AnimalCategory and have it return the correct variant and do exhaustive matching but it seems redundant, and I am not sure if I am doing it correctly.
-- snips --
impl AnimalCategory {
fn dog(self) -> Dog {
if let AnimalCategory::Dog(d) = self { d } else { panic!("Not dog!") }
}
fn cat(self) -> Cat {
if let AnimalCategory::Cat(c) = self { c } else { panic!("Not cat!") }
}
}
-- snips --
fn main() {
// OPTION 2
let animal = get_the_animal("dog");
if let AnimalCategory::Dog(Dog) = animal {
let dog = animal.dog();
walk_module(dog);
cry_module(dog); // this is where the redundancy comes
} else {
let cat = animal.cat();
walk_module(cat);
cry_module(cat); // this is where the redundancy comes
}
}
If I have to implement new methods, then I have to call the function/module twice. I would like to be able to do the OPTION 1 instead, but I could not figure it out.
Thread: how-to-avoid-exhaustive-matching-and-directly-return-value-of-enum-instead