I found writing Rust, using inheritance is rarely needed. However, in niche situations I think it would be a godsend. Here is an example:
struct Creature<E> {
hit_points : isize,
name : String,
extra : E
}
struct Demon<E> {
demon_domain : String,
extra : E
}
struct Imp<E> {
fireballs_left : usize,
extra : E
}
trait CreatureTrait {
fn announce(&self);
fn attack<F>(&mut self, target : &mut Creature<F>);
}
impl<E> CreatureTrait for Creature<E> {
default fn announce(&self) {
println!("{} enters.", self.name);
}
default fn attack<F>(&mut self, target : &mut Creature<F>) {
println!("{} makes a general attack on {}.", self.name, target.name);
}
}
impl<E> CreatureTrait for Creature<Demon<E>> {
default fn announce(&self) {
println!("{} ascends from the demonic place '{}'", self.name, self.extra.demon_domain);
}
default fn attack<F>(&mut self, target : &mut Creature<F>) {
println!("{} uses it's claws on {}", self.name, target.name);
}
}
impl<E> CreatureTrait for Creature<Demon<Imp<E>>> {
fn announce(&self) {
println!("A demonic imp ascends from the Abyss");
}
fn attack<F>(&mut self, target : &mut Creature<F>) {
println!("The imp throws a fireball at {}", target.name);
self.extra.extra.fireballs_left -= 1;
}
}
Now the following code will work, whether or not the Rust compiler knows the type of the objects at compile time:
fn main() {
let mut demon = Creature::<Demon::<()>> {
hit_points : 100,
name : "Asmodeus".to_string(),
extra : Demon {
demon_domain: "Hell".to_string(),
extra: ()
}
};
let mut target = Creature::<()> {
hit_points : 42,
name : "General Fighter".to_string(),
extra : ()
};
demon.announce();
demon.attack(&mut target)
}
The result is:
Asmodeus ascends from the demonic place 'Hell'
Asmodeus uses it's claws on General Fighter
This seems basically how to do OO in Rust. In my opinion it would be cleaner and more explicit with an extends keyword. At the risk of sounding heretical, is there any chance of an extends keyword in the future? Then the code would look something like this:
struct Creature {
hit_points : isize,
name : String,
}
struct Demon extends Creature {
demon_domain : String,
}
struct Imp extends Demon {
fireballs_left : usize,
}
trait CreatureTrait {
fn announce(&self);
fn attack(&mut self, target : &mut Creature);
}
impl CreatureTrait for Creature {
default fn announce(&self) {
println!("{} enters.", self.name);
}
default fn attack(&mut self, target : &mut Creature) {
println!("{} makes a general attack on {}.", self.name, target.name);
}
}
impl CreatureTrait for Demon {
default fn announce(&self) {
println!("{} ascends from the demonic place '{}'", self.name, self.demon_domain);
}
default fn attack(&mut self, target : &mut Creature) {
println!("{} uses it's claws on {}", self.name, target.name);
}
}
impl CreatureTrait for Imp {
fn announce(&self) {
println!("A demonic imp ascends from the Abyss");
}
fn attack<F>(&mut self, target : &mut Creature) {
println!("The imp throws a fireball at {}", target.name);
self.fireballs_left -= 1;
}
}