为具有已定义结构的枚举编写匹配语句的正确方法是什么?
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));
}
确实,对于您的解决方案,ElementKind
的每个实例都会包含冗余信息:变体本身(足以识别元素)及其数据(也足以识别元素) .
我希望枚举像我之前定义的结构的变体一样工作:
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));
}
确实,对于您的解决方案,ElementKind
的每个实例都会包含冗余信息:变体本身(足以识别元素)及其数据(也足以识别元素) .