【问题标题】:Derive a Trait for particular variants派生特定变体的特征
【发布时间】:2019-03-05 20:45:11
【问题描述】:

假设我有以下枚举

enum MyEnum {
  VariantA,
  VariantB,
  VariantC,
}

我可以通过这样做导出整个枚举的 PartialEq 特征

#[derive(PartialEq)]
enum MyEnum {
  VariantA,
  VariantB,
  VariantC,
}

我想要做的是派生特征,但仅限于特定变体而不是整个枚举。那可能吗? (或者它甚至有意义吗?)。

【问题讨论】:

  • 对我来说没有意义。特征派生是类型的编译时属性。变体是特定对象的运行时属性。听起来像XY problem。也许你应该描述你试图从中实现的行为。
  • 当你想比较两个对象时使用 PartialEq 或 Eq,假设你想检查MyEnum::VariantA == MyEnum::VariantB
  • 变体是来自其他 crate 的类型。并非所有人都实现了 PartialEq 特征。但我很乐意随时使用它;而且我更愿意将其保留为单个枚举。
  • 在这种情况下,您最好的选择可能是手动实现PartialEq (impl PartialEq for MyEnum),以便在将不受支持的变体之一用作操作数时返回false
  • @apemanzilla 是的,这将是我的最后选择。您实际上可以从 Rust 获取生成的代码并删除有问题的代码。但是每次使用更多变体更新枚举时都必须重做。

标签: enums rust traits


【解决方案1】:

假设您有这样的设置:

#[derive(PartialEq)]
struct VarB{
    pub value: u32,
}

#[derive(PartialEq)]
enum MyEnum{
    VarA(VarA),
    VarB(VarB)
}

VarA 来自不同的 crate,您无法编译,因为它没有派生 PartialEq(或任何其他外部特征)。

您可以使用 newtype 模式解决这个问题(假设您可以访问相关字段/访问器)

struct MyVarA(VarA);

impl PartialEq for MyVarA{
    fn eq(&self, other: &MyVarA) -> bool {
        self.0.value == other.0.value
    }

    fn ne(&self, other: &MyVarA) -> bool {
        self.0.value != other.0.value
    }
}

#[derive(PartialEq)]
struct VarB{
    value: u32,
}

#[derive(PartialEq)]
enum MyEnum{
    VarA(MyVarA),
    VarB(VarB)
}

更多信息: https://doc.rust-lang.org/rust-by-example/generics/new_types.html

【讨论】:

    【解决方案2】:

    我想要做的是派生特征,但仅限于特定变体而不是整个枚举。那可能吗? (或者它甚至有意义吗?)。

    这真的没有意义。

    类型实现了特征。枚举是一种类型,它的变体是它的值。您的问题等同于询问您是否可以为某些 Strings 而不是其他人实现 trait。

    如果不受支持的变体总是返回false 是可以接受的,类似于f32PartialEq 实现在比较NaN 值时返回false 的方式,那么您可以手动编写该impl :

    impl PartialEq for MyEnum {
        fn eq(&self, other: &MyEnum) -> bool {
            use MyEnum::*;
            match (self, other) {
                // VariantA and VariantB are supported
                (VariantA(value), VariantA(other_value)) => value == other_value,
                (VariantB(value), VariantB(other_value)) => value == other_value,
                // Any other combinations of variants end up here
                _ => false,
            }
        }
    }
    

    请注意,您必须以这种方式实现Eq,因为Eq 的实现可能被假定为total,但事实并非如此。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-14
      • 1970-01-01
      • 2018-02-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多