Rust 中的 A 型或 B 型

cho*_*ake 10 rust

A 有一个结构体,其属性可以有不同的类型

\n
#[derive(Debug, Deserialize, Serialize, Clone)]\npub struct A {\n    pub foo: B |\xc2\xa0C\n}\n\n#[derive(Debug, Deserialize, Serialize, Clone)]\npub struct B {\n    pub bar: usize\n}\n\n#[derive(Debug, Deserialize, Serialize, Clone)]\npub struct C {\n    pub bar2: usize\n}\n
Run Code Online (Sandbox Code Playgroud)\n

Rust 是否有可能实现类似的目标pub foo: B |\xc2\xa0C, so the type will be determined on runtime?

\n

Mas*_*inn 10

在 Rust 中是否有可能实现类似 pub foo: B | 的功能?C,所以类型将在运行时确定?

在 Rust 中执行此操作的方法是使用枚举来存储以下项之一:

#[derive(Debug, Deserialize, Serialize, Clone)]
pub enum A {
    B(B),
    C(C)
}

#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct B {
    pub bar: usize
}

#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct C {
    pub bar2: usize
}
Run Code Online (Sandbox Code Playgroud)

这里可以A两个值之一:A::B包含type 的值(以类似于单成员元组结构的方式)或包含 type 的值。并且不应混淆:前者本质上是一个函数,而后者是一种类型。BA::CCA::BB

从枚举中获取值的最基本方法是模式匹配

fn foo(a: A) {
    match a {
        A::B(b) => println!("Got a B: {:?}", b),
        A::C(c) => println!("Got a C: {:?}", c)
    }
}
Run Code Online (Sandbox Code Playgroud)

由于 Rust 枚举是完全标准的类型,您还可以向它们添加实用方法,这正是例如OptionResult工作的方式例如

impl A {
    fn b(&self) -> Option<&B> {
        if let A::B(b) = self { Some(b) } else { None }
    }
    fn c(&self) -> Option<&C> {
        if let A::C(c) = self { Some(c) } else { None }
    }
}

fn bar(a: A) {
    if a.b().is_some() {
        println!("Got a B!");
    } else {
        println!("Got a C :(");
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,由于您正在推导SerializeDeserialize因此我假设您还与外部系统(例如打字稿或其他系统)进行交互。

在这种情况下,您几乎肯定必须自定义枚举的序列化方案:serde 的默认值是外部标记,根据我的经验,这永远不是您要寻找的,因为它实际上不是其他语言倾向于用于其(正式的)的方案。或非正式的)工会。

内部标记和未标记更为常见,偶尔(罕见)会出现奇怪的相邻标记。