Enums 已知枚举变量时展开内部类型

Enums 已知枚举变量时展开内部类型,enums,rust,Enums,Rust,我有此枚举类型: enum Animal { Dog(i32), Cat(u8), } 现在我有一个函数,它将这个类型作为参数。我知道(出于某种原因)输入总是一个Cat。我想做到这一点: fn count_legs_of_cat(animal: Animal) -> u8 { if let Animal::Cat(c) = animal { c } else { unreachable!() } } 我可以写得更短和/或更地道吗?不太好。我看到的是为每个枚举变量

我有此枚举类型:

enum Animal {
    Dog(i32),
    Cat(u8),
}
现在我有一个函数,它将这个类型作为参数。我知道(出于某种原因)输入总是一个
Cat
。我想做到这一点:

fn count_legs_of_cat(animal: Animal) -> u8 {
    if let Animal::Cat(c) = animal { c } else { unreachable!() }
}

我可以写得更短和/或更地道吗?

不太好。我看到的是为每个枚举变量引入一个新的
struct
,然后使用枚举上的方法对其进行分解:

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
}
当然,您不需要结构,只需返回
u8
,但这可能很难跟踪

不过,在未来,这方面会有更好的支持。我认为这是最好的,但在博客文章中描述得更好。建议将
Animal::Cat
作为一个独立类型,这样您的方法就可以接受
Animal::Cat
,而不必担心它


就我个人而言,我几乎总是喜欢在我固有的实现中编写绝对正确的代码,并迫使调用方惊慌失措:

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
        }
    }
}

试试板条箱,它的工作原理和谢普马斯特的答案完全一样。

我倾向于将这种特性植入动物身上,比如说。对于简单的枚举,使用宏来生成impl应该相对容易,但这不是我经常使用的模式,所以我从来没有真正花时间来编写它……到2019年,这段代码实际上在稳定的环境下工作——自从提出这个问题以来,枚举得到了改进。请参阅:@alias65536该代码在当时也能正常工作。问题是,是否有更好的方法可以做到这一点。也许你可以添加一个例子,说明如何使用板条箱?
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,
        }
    }
}