Unwrap inner type when enum variant is known

前端 未结 1 520
悲哀的现实
悲哀的现实 2020-11-30 08:37

I have this enum type:

enum Animal {
    Dog(i32),
    Cat(u8),
}

Now I have a function that takes this type as parameter. I know

相关标签:
1条回答
  • 2020-11-30 09:06

    Not really. What I have seen is introducing a new struct for each enum variant, and then methods on the enum to decompose it:

    struct Dog(i32);
    struct Cat(u8);
    
    enum Animal {
        Dog(Dog),
        Cat(Cat),
    }
    
    impl Animal {
        fn cat(self) -> Cat {
            if let Animal::Cat(c) = self { c } else { panic!("Not a cat") }
        }
    
        fn dog(self) -> Dog {
            if let Animal::Dog(d) = self { d } else { panic!("Not a dog") }
        }
    }
    
    // Or better an impl on `Cat` ?
    fn count_legs_of_cat(c: Cat) -> u8 {
        c.0
    }
    

    Of course, you don't need the struct and you could just return the u8, but that may get hard to track.

    There's a glimmer of better support for this in the future, however. I think it's the "efficient code reuse" RFC, but better described in the blog post Virtual Structs Part 3: Bringing Enums and Structs Together. The proposal would be to allow Animal::Cat to be a standalone type, thus your method could accept an Animal::Cat and not have to worry about it.


    Personally, I almost always prefer to write the infallible code in my inherent implementation and force the caller to panic:

    impl Animal {
        fn cat(self) -> Option<Cat> {
            if let Animal::Cat(c) = self {
                Some(c)
            } else {
                None
            }
        }
    
        fn dog(self) -> Option<Dog> {
            if let Animal::Dog(d) = self {
                Some(d)
            } else {
                None
            }
        }
    }
    

    And I'd probably use a match

    impl Animal {
        fn cat(self) -> Option<Cat> {
            match self {
                Animal::Cat(c) => Some(c),
                _ => None,
            }
        }
    
        fn dog(self) -> Option<Dog> {
            match self {
                Animal::Dog(d) => Some(d),
                _ => None,
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题