We have a struct A
with some fields and some of its "instance" are special and some fields does not make sense to them.
Both the normal A
s and the special A
s will generally need to be processed together in a Vec
. They are generally created from different ways like calling different APIs and put into the Vec
.
As a newbie, I come up with the following solutions:
First: Enum way
#[derive(Default)]
struct NormalA {
pub val: i32,
pub created: String,
}
#[derive(Default)]
struct SpecialA {
pub val: i32,
}
enum A {
Normal(NormalA),
Special(SpecialA),
}
fn do_with_a(a: &A) {
match a {
A::Normal(inner) => println!("{:#?}", inner.val),
A::Special(inner) => println!("{:#?}", inner.val),
}
}
fn main() {
let many_as = vec![
A::Normal(NormalA {
val: 1,
created: "now".to_owned(),
}),
A::Normal(NormalA {
val: 2,
created: "yesterday".to_owned(),
}),
A::Special(SpecialA { val: -1 }),
];
for a in &many_as {
do_with_a(a);
}
}
Second: Option way
#[derive(Default)]
struct A {
pub val: i32,
pub created: Option<String>,
}
impl A {
fn is_special(&self) -> bool {
self.val < 0
}
}
fn do_with_a(a: &A) {
println!("{:#?}", a.val);
}
fn main() {
let many_as = vec![
A {
val: 1,
created: Some("now".to_owned()),
},
A {
val: 2,
created: Some("yesterday".to_owned()),
},
A {
val: -1,
created: None,
},
];
for a in &many_as {
do_with_a(a);
}
}
The first way use enum
to differentiate the normal ones and special ones. Generally need more code to match
the enum and to create the "instances". The type system requires one to check the special case in every usage.
The second way make some fields optional to adapt for the special ones. The Some
or None
is not elegant on fields. Also need methods like is_special
to check whether one is special.
Question:
If
- many times the normal ones and the specials need to be put into a collection to be processed together,
- sometimes the special ones need to be process specially (not shown in the example)
- the numbers of special "instance" is very small (assumed less than 3), (thus I'm not sure if they worths a different struct)
- the numbers of the fields in normal
A
is very large (assumed 20) - about half of the fields are not meaningful for special
A
(thus the second way would contains manySome
s)
then which way is better? Or is there any other better way to handle this?
Thanks.