为具有已定义结构的枚举编写匹配语句的正确方法是什么?

What is the correct way to write the match statement for an enum with already defined structs?

我希望枚举像我之前定义的结构的变体一样工作:

pub struct Element {
    symbol: String,
    atomic_number: u8,
    atomic_mass: f32,
}
pub struct Hydrogen {
    element: Element,
}
pub struct Helium {
    element: Element,
}
pub struct Lithium {
    element: Element,
}
pub enum ElementKind {
    HYDROGEN(Hydrogen),
    HELIUM(Helium),
    LITHIUM(Lithium,
}

impl Default for Hydrogen {
    fn default() -> Self {
        Hydrogen {
            element: Element {
                symbol: "H".to_string(),
                atomic_number: 1,
                atomic_mass: 1.008,
            },
        }
    }
}

impl Default for Helium {
    fn default() -> Self {
        Helium {
            element: Element {
                symbol: "He".to_string(),
                atomic_number: 2,
                atomic_mass: 4.003,
            },
        }
    }
}

impl Default for Lithium {
    fn default() -> Self {
        Lithium {
            element: Element {
                symbol: "Li".to_string(),
                atomic_number: 3,
                atomic_mass: 6.491,
            },
        }
    }
}

fn main() {
    let e = ElementKind::HYDROGEN;
    match e {
        // TODO
    }
}

编写 match 语句的正确方法是什么,例如,始终打印出元素的 symbol

写的时候

struct Foo {
    foo: u32,
}

enum Bar {
    Foo,
}

Foo 结构和 Bar::Foo 变体之间绝对没有关系。他们只是碰巧有相同的名字。 (另请参阅 )。

解决这个问题的通常方法是在变体中有一个字段:

enum Bar {
    // The first Foo is the variant name, the second Foo a field of type Foo
    Foo(Foo),
}

或在枚举中内联结构(即使用 struct 变体):

enum Bar {
    Foo {
        foo: u32,
    }
}

但是在您的情况下,我认为您不需要为每个元素创建一个结构,只需执行以下操作即可:

#[derive(Debug)]
pub struct Element {
    symbol: String,
    atomic_number: u8,
    atomic_mass: f32,
}

pub enum ElementKind {
    Hydrogen,
    Helium,
    Lithium,
}

impl From<ElementKind> for Element {
    fn from(e: ElementKind) -> Element {
        use ElementKind::*;

        match e {
            Hydrogen => Element {
                symbol: "H".to_string(),
                atomic_number: 1,
                atomic_mass: 1.008,
            },
            Helium => Element {
                symbol: "He".to_string(),
                atomic_number: 2,
                atomic_mass: 4.003,
            },
            Lithium => Element {
                symbol: "Li".to_string(),
                atomic_number: 3,
                atomic_mass: 6.491,
            },
        }
    }
}

fn main() {
    let e = ElementKind::Hydrogen;
    println!("{:#?}", Element::from(e));
}

(Permalink to the playground)

确实,对于您的解决方案,ElementKind 的每个实例都会包含冗余信息:变体本身(足以识别元素)及其数据(也足以识别元素) .