我能在Rust中将结构体嵌入枚举吗?

3

我有这样的代码:

enum Packet {
    Quit,
    Message {
        text: String,
        time: i32,
        is_admin: bool,
    },
}

这样做很方便,但我不喜欢嵌套结构体。想象一下,如果我需要在这个枚举中添加更多的项,那么Packet定义就会变得太大了。 那么,有没有办法将Message结构体移出来,并在Packet结构体的定义中只写它的名称呢? 我考虑过这样做:

struct ChatMessage {
    text: String,
    time: i32,
    is_admin: bool,
}
enum Packet {
    Quit,
    Message(ChatMessage),
}
< p > (顺便问一下,我可以将结构体命名为Packet中的项(struct MessageMessage(Message))吗?)
但是这样我就必须做let msg = message.0或类似的事情。如果这是唯一的解决方案 - 我可以接受,但如果有更简洁的解决方案,我会很高兴。


我很难理解你的问题。两个例子都可以,不用担心枚举大小。 - Stargateur
@Stargateur 我认为他们指的是源代码大小,也就是当类似结构体的变量数量增加时,枚举定义会变得冗长且不易操作,因为每个变量的字段都会在枚举定义中添加一行。 - Masklinn
1个回答

10

虽然方便,但我不喜欢这样嵌套结构体。

它并不是嵌套的结构体,而是类似结构体的变种。

那么,有没有办法将Message结构体移到外面,只需在Packet结构体的定义中写下它的名称即可?我考虑过这样做:

你可以完全这样做,它直接就能用,这是一种非常常见的模式。

(顺便问一下,我可以把Message结构体的名字取成和Packet中的项一样吗(struct Message, Message(Message))?)

可以,二者之间实际上没有任何关系:Packet::MessagePacket 枚举的构造函数,而 Message 则是一个无关的(但嵌入的)类型。

但这样我就必须做 let msg = message.0 或者类似的事情了。

是的和否的,枚举需要某种形式的模式匹配,所以在所有情况下,您都必须匹配您的Packet变量。对于第一个版本,您可以直接提取变体的字段:

match packet {
    Quit => todo!("something"),
    Message { text, .. } => todo!("something with {}", text)
}

使用第二种方法,您可以提取 Message,并从那里获取其内容:

match packet {
    Quit => todo!("something"),
    Message(m) => todo!("something with {}", m.text)
}

然而,模式具有无限的“深度”,因此您可以同时完成两者,只不过会更加冗长:

match packet {
    Quit => todo!("something"),
    Message(ChatMessage { text, .. }) => todo!("something with {}", text)
}

演示(不完整):https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=b2bdaf08c45424f507955790445cc2f9


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接