当枚举变量已知时解开内部类型 [英] Unwrap inner type when enum variant is known

查看:29
本文介绍了当枚举变量已知时解开内部类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个枚举类型:

enum Animal {狗(i32),猫(u8),}

现在我有一个将这种类型作为参数的函数.我知道(出于某种原因)输入总是一个Cat.我想实现这一目标:

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

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

解决方案

并非如此.我所看到的是为每个枚举变体引入一个新的 struct,然后在枚举上分解它的方法:

struct Dog(i32);结构猫(u8);枚举动物{狗(狗),猫(猫),}impl 动物 {fn cat(self) ->猫 {if let Animal::Cat(c) = self { c } else { panic!("Not a cat") }}fn 狗(自我)->狗 {if let Animal::Dog(d) = self { d } else { panic!("Not a dog") }}}//或者更好的实现 `Cat` ?fn count_legs_of_cat(c: Cat) ->u8{c.0}

当然,您不需要需要结构体,您可以只返回u8,但这可能很难跟踪.

不过,未来会对此提供更好的支持.我认为这是高效代码重用"RFC,但更好地描述在博客文章 虚拟结构第 3 部分:将枚举和结构结合在一起.提议是允许 Animal::Cat 成为独立类型,因此您的方法可以接受 Animal::Cat 而不必担心它.><小时>

就我个人而言,我几乎总是喜欢在我的固有实现中编写无误的代码并迫使调用者恐慌:

impl 动物 {fn cat(self) ->选项<猫>{如果让动物::猫(c) = self {一些(c)} 别的 {没有任何}}fn 狗(自我)->选项<狗>{如果让动物::狗(d) = self {一些(d)} 别的 {没有任何}}}

我可能会使用 match

impl 动物 {fn cat(self) ->选项<猫>{匹配自我{动物::猫(c) =>一些(c),_ =>没有任何,}}fn 狗(自我)->选项<狗>{匹配自我{动物::狗(d) =>一些(d),_ =>没有任何,}}}

I have this enum type:

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

Now I have a function that takes this type as parameter. I know (for some reason) that the input is always a Cat. I want to achieve this:

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

Can I write this shorter and/or more idiomatic?

解决方案

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

这篇关于当枚举变量已知时解开内部类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆