rust mopa
#[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); }