首页 > 解决方案 > 两种类型的派送应该怎么做?

问题描述

在这段代码中:

impl Msg {
    fn apply_to(&self, state: &mut State) {
        match (self, state) {
            (Msg::MsgA(m), State::StateOne(s)) => {
                m.apply_to_state_one(s);
            },

            (Msg::MsgB(m), State::StateOne(s)) => {
                m.apply_to_state_one(s);
            },

            // FIXME: can these two dispatches be made into one
            (Msg::MsgC(m), State::StateOne(s)) => {
                m.apply_to_common_state(&mut s.common);
            },
            (Msg::MsgC(m), State::StateTwo(s)) => {
                m.apply_to_common_state(&mut s.common);
            },
        
            (Msg::MsgD(m), State::StateTwo(s)) => {
                m.apply_to_state_two(s);
            },
        
            (_, _) => { // don't care
                ()
            }
        }
    }
}

有没有吸引力的样板,更多的是在完整的操场上。

全文:https ://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=acca055b435ae21d141eaac70e097e72

我希望每个Msg都能够应用于 a StateOne, aStateTwo或其中之一(通过它们的公共字段,common)。

Msgs 在应用于他们没有实现的状态时应该出错。

我希望所有逻辑都在单个消息中,没有任何逻辑MsgStates。

如何在 Rust 的类型系统中最好地表达这一点?


更新:我特别想知道我解决这个问题的一般方法是否适用于 Rust,或者如果消息或状态是泛型或dyn trait对象,是否有更好的解决方案。

标签: enumsrust

解决方案


您可以考虑使用结构解构来组合它们:

(Msg::MsgC(m), State::StateOne(StateOne {mut common, ..}))
| (Msg::MsgC(m), State::StateTwo(StateTwo {mut common, ..})) => {
    m.apply_to_common_state(&mut common);
},

它不是最漂亮的,但是在or 模式稳定之后,它可能会减少到(Msg::MsgC(m), State::StateOne(StateOne {mut common, ..}) | State::StateTwo(StateTwo {mut common, ..})).


推荐阅读