【问题标题】:How should dispatches on two types be done?两种类型的派送应该怎么做?
【发布时间】:2020-08-02 15:27:03
【问题描述】:

在这段代码中:

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 都能够应用于StateOneStateTwo 或任何一个(通过它们的公共字段common)。

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

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

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


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

【问题讨论】:

    标签: enums rust


    【解决方案1】:

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

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

    这不是最漂亮的,但是在or patterns 稳定之后,它可能会变成(Msg::MsgC(m), State::StateOne(StateOne {mut common, ..}) | State::StateTwo(StateTwo {mut common, ..}))

    【讨论】:

    • 感谢您的回答。这些解决方案虽然是有用的改进,但仍然没有让我觉得我做对了。 (我会写一个Java解决方案,作为比较。)
    猜你喜欢
    • 2013-10-23
    • 2023-01-26
    • 2016-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多