We can find the example in the rust book at chapter 16.2 "Returning traits with dyn".
Here is some sample code based on the question. I put the functions with the Answer to the question at the top of the file so it's easier to read for newcomers.
fn main() {
//Initialise game
//New empty struct
let pencil = Pencil {};
//We need Box <dyn TraitName> because Drawable can be: Player or a Chest, here it's a player
let player: Box<dyn Drawable> = create_player_or_chest(true);
//We need Box <dyn TraitName> because Drawable can be: Player or a Chest, here it's a chest
let chest: Box<dyn Drawable> = create_player_or_chest(false);
//Play game
player.draw(&pencil);
chest.draw(&pencil);
}
fn create_player_or_chest(is_player:bool) -> Box<dyn Drawable > {
if is_player {
println!("GAME INIT: Creating a new player");
Box::new(Player {
hp: 100,
atk: 2,
entity: Entity {
name: String::from("Mage")
}
})
} else {
println!("GAME INIT: Creating a new chest");
Box::new(Chest {
amount: 1,
entity: Entity {
name: String::from("Withering staff")
}
})
}
}
impl Drawable for Chest {
fn draw(&self, pencil: &Pencil) {
println!("Drawing chest with amount of items: {}", self.amount);
pencil.draw(&self.entity);
}
}
impl Drawable for Player {
fn draw(&self, pencil:&Pencil) {
println!("Drawing player with hp: {} and atk: {}", self.hp, self.atk);
pencil.draw(&self.entity);
}
}
impl Pencil {
fn draw(&self, entity: &Entity) {
println!("{}", entity.name);
}
}
trait Drawable {
fn draw(&self, pencil: &Pencil);
}
struct Entity {
name: String,
}
struct Player {
entity: Entity,
hp: i32,
atk: i32
}
struct Chest {
entity: Entity,
amount: i32
}
struct Pencil {}