How to implement a generic data type to another struct's method?

Viewed 34

I have this code:

#[derive(Debug)]
pub struct Counter {
    pub calories: f64,
}

pub struct Protein {
    pub weight_in_kg: f64,
}

pub struct Fat {
    pub weight_in_kg: f64,
}

impl Counter {
    fn eat(&mut self, food: T) {
        self.calories += food.gives();
    }
}

pub trait Food {
    fn gives(&self) -> f64;
}

impl Food for Protein {
    fn gives(&self) -> f64 {
        self.weight_in_kg * 4.0
    }
}

impl Food for Fat {
    fn gives(&self) -> f64 {
        self.weight_in_kg * 9.0
    }
}

Which gives this error:

fn eat(&mut self, food: T) { ^ not found in this scope

T can either be Protein or Fat. But I am not sure where to implement T to get it working.

1 Answers

You need to make eat a generic, like this:

impl Counter {
    // This means make a copy of this method for every used value of `T`
    // Use :Food to make sure `T` can only be food
    fn eat<T: Food>(&mut self, food: T) {
        self.calories += food.gives();
    }
}

Alternatively:

impl Counter {
    // This method is often used if you need more complex trait bounds.
    fn eat<T>(&mut self, food: T)
        where T: Food
    {
        self.calories += food.gives();
    }
}

You can also make the entire struct a generic, in that case each counter can eat only one kind of food.

Related