0

I'd like to create different 'flavors' of a struct. This means that depending on which enum I'm passing into the structure's constructor I'll get a version of the structure whose 'flavor' trait's type depends on that enum value. I know that I must specify a single type for my structure's fields, but what if I want that type to change based on the value I'm passing into the constructor? Can I only do something like this using traits?

pub struct ChocolateFlavor {
    coco: u32,
}

pub struct VanillaFlavor {
    bean: u32,
}

pub struct IceCream {
    flavor: (), //should be able to be ChocholateFlavor or VanillaFlavor
}

pub enum Flavors {
    Vanilla,
    Chocholate,
}

impl IceCream {
    pub fn new(input_type: Flavors) -> Self {
        match input_type {
            Flavors::Vanilla => input = VanillaFlavor,
            Flavors::Chocholate => input = ChocolateFlavor,
        }
        let mut new_icecream = LabeledInput { flavor: input };
        new_icecream
    }
}

fn main() {
    //give me a chocholate ice cream
    let mut my_chocholate = IceCream::new(Flavors::Chocolate);
    //give me a vanilla ice cream
    let mut my_vanilla = IceCream::new(Flavors::Vanilla);
}
ANimator120
  • 2,556
  • 1
  • 20
  • 52
  • Enum variants aren't their own types, so no. – Shepmaster Dec 14 '20 at 19:18
  • 1
    Look at it this way: `fn example(flavor: Flavor) { IceCream::new(flavor); }` How much space on the stack will be required? How does the compiler know that **at compile time**? – Shepmaster Dec 14 '20 at 19:21
  • See also [Defining a method for a struct only when a field is a certain enum variant?](https://stackoverflow.com/q/48120780/155423) – Shepmaster Dec 14 '20 at 19:22
  • @Shepmaster I see. If this is not possible, would you recommend the 'hoisiting' strategy outlined in that response? – ANimator120 Dec 14 '20 at 19:27
  • 1
    Yes. You can mix the concepts as well, by having a struct with a generic (e.g. `struct IceCream`) and then put that into your second enum (`enum Whatever { Choc(IceCream), Van(IceCream) }`). – Shepmaster Dec 14 '20 at 19:34
  • 1
    It looks like you're making a habit of just putting `mut` everywhere -- that tends to make your life more error-prone. – Mike Graham Dec 15 '20 at 06:15

1 Answers1

2

You can use enums with values

enum FlavorData {
    ChocolateFlavor { coco: u32 },
    VanillaFlavor { bean: u32 },
}

pub struct IceCream {
    flavor: FlavorData,
}

pub enum Flavors {
    Vanilla,
    Chocolate,
}

impl IceCream {
    pub fn new(input_type: Flavors) -> Self {
        let flavor = match input_type {
            Flavors::Vanilla => FlavorData::VanillaFlavor { bean: 10 },
            Flavors::Chocolate => FlavorData::ChocolateFlavor { coco: 20 },
        };
        IceCream { flavor: flavor }
    }
}

fn main() {
    //give me a chocholate ice cream
    let mut my_chocolate = IceCream::new(Flavors::Chocolate);
    //give me a vanilla ice cream
    let mut my_vanilla = IceCream::new(Flavors::Vanilla);
}
Mike Graham
  • 73,987
  • 14
  • 101
  • 130