#[macro_use]
extern crate mopa;
struct Bear {
// This might be a pretty fat bear.
fatness: u16,
}
impl Bear {
fn eat(&mut self, person: Box<dyn Person>) {
self.fatness = (self.fatness as i16 + person.weight()) as u16;
}
}
trait Person: mopa::Any {
fn panic(&self);
fn yell(&self) { println!("Argh!"); }
fn sleep(&self);
fn weight(&self) -> i16;
}
mopafy!(Person);
struct Benny {
// (Benny is not a superhero. He can’t carry more than 256kg of food at once.)
kilograms_of_food: u8,
}
impl Person for Benny {
fn panic(&self) { self.yell() }
fn sleep(&self) { /* ... */ }
fn weight(&self) -> i16 {
// Who’s trying to find out? I’m scared!
self.yell();
self.kilograms_of_food as i16 + 60
}
}
struct Chris;
impl Chris {
// Normal people wouldn’t be brave enough to hit a bear but Chris might.
fn hit(&self, bear: &mut Bear) {
println!("Chris hits the bear! How brave! (Or maybe stupid?)");
// Meh, boundary conditions, what use are they in examples?
// Chris clearly hits quite hard. Poor bear.
bear.fatness -= 1;
}
}
impl Person for Chris {
fn panic(&self) { /* ... */ }
fn sleep(&self) { /* ... */ }
fn weight(&self) -> i16 { -5 /* antigravity device! cool! */ }
}
fn simulate_simulation(person: Box<dyn Person>, bear: &mut Bear) {
if person.is::<Benny>() {
// None of the others do, but Benny knows this particular
// bear by reputation and he’s *really* going to be worried.
person.yell()
}
// If it happens to be Chris, he’ll hit the bear.
person.downcast_ref::<Chris>().map(|chris| chris.hit(bear));
bear.eat(person);
}
fn main() {
let mut bear = Bear { fatness: 10 };
simulate_simulation(Box::new(Benny { kilograms_of_food: 5 }), &mut bear);
simulate_simulation(Box::new(Chris), &mut bear);
}