Можно ли переходить на черту характера при разрушении перечислений? - PullRequest
0 голосов
/ 08 мая 2018

Я хотел бы иметь возможность деструктурировать / перебросить варианты перечисления в общепринятую черту. Вот настройки:

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 голосов
/ 08 мая 2018

Нет, вы не можете , пока деструктурируетесь. Вы можете сделать это после хотя:

// 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()
    }
}
...