rust 我可以用额外的值扩展枚举吗?

8ehkhllq  于 2023-05-07  发布在  其他
关注(0)|答案(2)|浏览(119)

如果我有一个带有一组值的枚举,有没有一种方法可以创建第二个具有相同变量的枚举?

// From this
enum Base {
    Alpha,
    Beta(usize),
}

// To this, but without copy & paste
enum Extended {
    Alpha,
    Beta(usize),
    Gamma,
}
az31mfrm

az31mfrm1#

枚举不能直接扩展,但可以使用与结构体相同的组合技巧(即,对于结构体,可以有一个存储“父”示例的字段)。

enum Base {
    Alpha,
    Beta(usize),
}

enum Extended {
    Base(Base),
    Gamma
}

如果您希望单独处理每种情况,则可以像

match some_extended {
    Base(Alpha) => ...,
    Base(Beta(x)) => ...,
    Gamma => ...
}

但是你也可以共享/重用来自“父”的代码

match some_extended {
    Base(base) => base.do_something(),
    Gamma => ...,
}
lpwwtiir

lpwwtiir2#

你不能,但是你可以要求泛型类型是枚举T的超集。
在某些严格限制的情况下,这是有用的,但它可以解决“无法扩展枚举”的问题,特别是关于事件。
在特定的情况下,如果你有一个对事件类型TEvent通用的库,但库也有内部事件,你经常会遇到库将接受 Package 器事件类型的参数的情况,比如:

enum TLibEvent<T> {
  CustomEvent(T),
  InternalEvent(MyInternalEventType)
}

如可接受的解决方案中所述。但是,您不需要这样做。
您可以通过向库要求通用事件类型的From<MyInternalEventType>来使用单个平顶事件类型。
示例:(请看最下面的部分,了解这在实践中是如何工作的)

enum Events {
    A,
    B
}

#[derive(Debug)]
struct Foo<T> {
    pub events: Vec<T>
}

impl<T: From<Events> + PartialEq> Foo<T> 
{
    pub fn new() -> Foo<T> {
        Foo {
            events: Vec::new()
        }
    }
    
    pub fn trigger_event(&mut self, event: T) {
        self.events.push(event);
    }
    
    fn internal_action(&mut self) {
        self.trigger_event(T::from(Events::A));
        self.trigger_event(T::from(Events::B));
    }
    
    pub fn initialize(&mut self) {
        self.internal_action();
    }
    
    pub fn add(&mut self, event: T) {
        self.events.push(event);
    }
    
    pub fn any_events<TIn: Into<T>>(&self, event: TIn) -> bool {
        let custom_event:T = event.into();
        self.events.iter().any(|e| *e == custom_event)
    }
}

#[derive(PartialEq, Debug)]
enum AppEvents {
    A,
    B,
    C
}

impl From<Events> for AppEvents {
    fn from(value: Events) -> Self {
        match value {
            Events::A => AppEvents::A,
            Events::B => AppEvents::B,
        }
    }
}

fn main() {
  let mut foo = Foo::<AppEvents>::new();
  assert!(!foo.any_events(Events::A));
  assert!(!foo.any_events(Events::B));
  
  foo.initialize();
  foo.add(AppEvents::C);
 
  // Interact with foo using either internal or external events
  assert!(foo.any_events(AppEvents::C)); 
  assert!(foo.any_events(Events::A));
  assert!(foo.any_events(Events::B));
  
  println!("{:?}", foo);
}

RustPlayground链接:https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=cf82e44ae4f438c0b3308b54ffb36ffa

相关问题