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

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

问题描述

我有这个枚举类型:

 枚举动物{
狗(i32),
猫(u8),
}

现在我有一个将此类型作为参数的函数。我知道(由于某种原因)输入始终是 Cat 。我想实现这一点:

  fn count_legs_of_cat(animal:Animal) - > u8 {
如果让Animal :: Cat(c)= animal {c} else {unreachable!()}
}

我可以写这个更短和/或更多的惯用语?

解决方案

不是真的。我看到的是为每个枚举变体引入一个新的 struct ,然后枚举枚举的方法:

  struct Dog(i32); 
struct Cat(u8);

enum动物{
狗(狗),
猫(猫),
}

impl动物{
fn猫(自) - >猫{
如果让Animal :: Cat(c)= self {c} else {panic!(Not a cat)}
}

fn dog(self) - >狗{
如果让Animal :: Dog(d)= self {d} else {panic!(Not a dog)}
}
}

//或者更好地说猫?
fn count_legs_of_cat(c:Cat) - > u8 {
c.0
}

当然,你不需要结构,你可以返回 u8 ,但可能会很难跟踪。



然而,将来有一丝更好的支持。我认为是高效代码重用RFC ,但更好地描述在博客文章虚拟结构第3部分:将枚举和结构化在一起。该建议将允许 Animal :: Cat 成为独立类型,因此您的方法可以接受 Animal :: Cat 而不必担心。






个人而言,我几乎总是喜欢在我固有的实施并强制呼叫者惊慌:

  impl动物{
fn cat(self) - >选项<目录> {
如果让Animal :: Cat(c)= self {
Some(c)
} else {

}
}

fn dog(self) - >选项<狗和GT; {
如果让Animal :: Dog(d)= self {
Some(d)
} else {

}
}
}

我可能会使用匹配

  impl动物{
fn cat(self) - >选项<目录> {
match self {
Animal :: Cat(c)=>一些(c),
_ =>没有,
}
}

fn dog(self) - >选项<狗和GT; {
match self {
Animal :: Dog(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天全站免登陆