This is a playground showcasing 2 ways to create a vector holding elements of different types
Assume you have two structs Support and Bend that share common behaviours like having coordinates in space with the struct Coordinates.
struct Support {
coordinates: Coordinates,
// Other `Support` specific fields
}
struct Bend {
coordinates: Coordinates,
// Other `Bend` specific fields
}
struct Coordinates {
x: f32,
y: f32,
z: f32,
}In order to create a vector that can hold either type and access the shared behaviour we have the following two approaches.
Create a enum containing tuple-like variants.
enum NodeEnum {
Support(Support),
Bend(Bend),
}Implement functions with desired behaviour via pattern matching for this enum
impl NodeEnum {
fn coordinates(&self) -> Coordinates {
match self {
NodeEnum::Support(support) => support.coordinates.clone(),
NodeEnum::Bend(bend) => bend.coordinates.clone(),
}
}
}Create a vector of the type Vec<NodeEnum> and push elements
pub fn enum_vec() {
let mut vec: Vec<NodeEnum> = Vec::new();
vec.push(NodeEnum::Support(Support::default()));
vec.push(NodeEnum::Bend(Bend::default()));
println!("\nVector with Enum:\n");
for element in vec {
// Access shared behaviour
println!("{:?}", element.coordinates())
}
}Create a trait NodeTrait with a prototype function of the desired behaviour
trait NodeTrait {
fn coordinates(&self) -> Coordinates;
}Implement the trait and functions with a body for the structs
impl NodeTrait for Support {
fn coordinates(&self) -> Coordinates {
self.coordinates.clone()
}
}
impl NodeTrait for Bend {
fn coordinates(&self) -> Coordinates {
self.coordinates.clone()
}
}Create a vector of type Vec<Box<dyn Trait>> and push elements
pub fn trait_vec() {
let mut vec: Vec<Box<dyn NodeTrait>> = Vec::new();
vec.push(Box::new(Support::default()));
vec.push(Box::new(Bend::default()));
println!("\nVector with Box<dyn Trait>:\n");
for element in vec {
// Access shared behaviour
println!("{:?}", element.coordinates())
}
}