0

I have an enum with around 20 variants. As traits cannot be implemented for enum's variants (see Can traits be used on enum types? and How do I implement a trait for an enum and its respective variants?) I have implemented my trait for some of the types embedded in the variants.

Given a variable typed as the enum, what is the idiomatic/best way to access the trait? As I need to use this in different places, I tried to move the code in a function and my following attempt returns a Option<Box<&dyn Trait>>.

pub struct X { pub name: String, pub weight: u32 }
pub struct Y { pub name: String }
pub struct Z {}

pub enum Node {
    X(X),
    Y(Y),
    Z(Z),
}

pub trait Weighted {
    fn weight(&self) -> u32;
}

impl Weighted for X {
    fn weight(&self) -> u32 { return self.weight; }
}

impl Weighted for Z {
    fn weight(&self) -> u32 { return 3; }
}

pub fn as_weighted_node(node: &Node) -> Option<Box<&dyn Weighted>> {
    match node {
        Node::X(x) => Some(Box::new(x)),
        Node::Z(z) => Some(Box::new(z)),
        _ => None
    }
}

let node: Node = Node::X(X { name: "x1".to_string(), weight: 1 });

println!("{}", as_weighted_node(&node).unwrap().weight());
vhiairrassary
  • 354
  • 1
  • 2
  • 12
  • 3
    Your code works, so it seems like you have an answer to your question — that's great! You should post it as an answer rather than an edit to your question and then potentially accept that answer. That way, the question shows up as solved in search results, people can vote on your answer or provide alternative answers, and your solution can be more helpful to future people with the same problem. – Shepmaster Aug 11 '21 at 17:01

1 Answers1

0

It seems Box is not needed and as_weighted_node can be written as:

pub fn as_weighted_node(node: &Node) -> Option<&dyn Weighted> {
    match node {
        Node::X(x) => Some(x),
        Node::Z(z) => Some(z),
        _ => None
    }
}

I am still not sure this is the best way to handle this issue though.

vhiairrassary
  • 354
  • 1
  • 2
  • 12