How to send different structs in a function of a trait?

Viewed 55
enum Property {
    Triangle(TriangleProperty),
    Square(SquareProperty),
}

struct Triangle {
    x: u8,
    y: Vec<u8>,
}

struct Square {
    x: u8,
    y: String,
}

struct TriangleProperty {
    a: u8,
    b: u8,
    c: u8,
}

struct SquareProperty {
    a: u8,
    b: u8,
    c: u8,
    d: u8,
}

trait Shape {
    fn do_magic(&self, p: Property) -> u64;
}

impl Shape for Triangle {
    fn do_magic(&self, p: Property) -> u64 {
        match (p) {
            Triangle(x) => { /* do something with x */ }
            _ => panic("this wont happen"),
        }
    }
}

impl Shape for Square {
    fn do_magic(&self, p: Property) -> u64 {
        match (p) {
            Square(x) => { /* do something with x */ }
            _ => panic("this wont happen"),
        }
    }
}

As you can see I'm calling panic which i don't think is good way to deal with this.

This is just an example but I cannot have TriangleProperty inside the Triangle struct. Because I'm using TriangleProperty as an input in the function do_magic that uses a constant immutable Triangle struct. So the only option i can think of is wrapping in an enum. But is there any better way to do this ?

1 Answers

This looks like a use case for an associated type:

trait Shape {
    type Property;
    fn do_magic(&self, p: Self::Property) -> u64;
}

impl Shape for Triangle {
    type Property = TriangleProperty;
    fn do_magic(&self, p: Self::Property) -> u64 {
        /* do something with p */
    }
}

impl Shape for Square {
    type Property = SquareProperty;
    fn do_magic(&self, p: Self::Property) -> u64 {
        /* do something with p */
    }
}

When you implement Shape you choose what type Self::Property will be, and within the impl you can use it as the concrete type. The compiler will not allow you to pass a SquareProperty to Triangle::do_magic or vice versa.

Related