在解构枚举时,是否有可能将其转化为特征?

时间:2018-05-08 16:19:57

标签: enums rust traits upcasting

我希望能够将枚举变体构造/转换为常用的特征。这是设置:

trait SomeTrait {
    fn some_func(&self);
}

struct SomeStruct1;
impl SomeTrait for SomeStruct1 {
    fn some_func(&self) {}
}

struct SomeStruct2;
impl SomeTrait for SomeStruct2 {
    fn some_func(&self) {}
}

enum SomeEnum {
    Value1(SomeStruct1),
    Value2(SomeStruct2),
}

这是我尝试的一种可能性:

fn call_some_func(some_enum: SomeEnum) {
    match some_enum {
        SomeEnum::Value1(ref some_trait: &SomeTrait) |
        SomeEnum::Value2(ref some_trait: &SomeTrait) => some_trait.some_func()
    }
}

导致此错误:

error: expected one of `)`, `,`, or `@`, found `:`
  --> src/main.rs:22:40
   |
22 |         SomeEnum::Value1(ref some_trait: &SomeTrait) |
   |                                        ^ expected one of `)`, `,`, or `@` here

这是我的另一个想法:

fn call_some_func2(some_enum: SomeEnum) {
    match some_enum {
        _(ref some_trait: &SomeTrait) => some_trait.some_func()
    }
}

哪个也失败了:

error: expected one of `=>`, `if`, or `|`, found `(`
  --> src/main.rs:22:10
   |
22 |         _(ref some_trait: &SomeTrait) => some_trait.some_func()
   |          ^ expected one of `=>`, `if`, or `|` her

有没有人知道如何实现这种类型的解构?

1 个答案:

答案 0 :(得分:3)

不,解构时你不能。您可以在之后执行此操作:

// My preferred
fn call_some_func(some_enum: SomeEnum) {
    let x: &SomeTrait = match some_enum {
        SomeEnum::Value1(ref x) => x,
        SomeEnum::Value2(ref x) => x,
    };
    x.some_func();
}
// Also works
fn call_some_func(some_enum: SomeEnum) {
    let x = match some_enum {
        SomeEnum::Value1(ref x) => x as &SomeTrait,
        SomeEnum::Value2(ref x) => x,
    };
    x.some_func();
}

我鼓励您将其提取到一种重用方法:

impl SomeEnum {
    fn as_trait(&self) -> &SomeTrait {
        match *self {
            SomeEnum::Value1(ref x) => x,
            SomeEnum::Value2(ref x) => x,
        }
    }
}

fn call_some_func(some_enum: SomeEnum) {
    some_enum.as_trait().some_func();
}

如果所有变体实现它,可能要在枚举本身上实现特征。这样,消费者就不必关心:

impl SomeTrait for SomeEnum {
    fn some_func(&self) {
        self.as_trait().some_func()
    }
}