Hello,
I don't want to create controversy with this post, but I find that inheritance is a very important feature, and the "trait" system doesn't fully meet the need.
Let's take this simplistic example :
trait InfoAnimal {
fn say_hello() -> String;
fn get_number_of_legs(&self) -> u32;
}
struct Animal {
number_of_legs: u32,
is_domestic: bool,
}
impl Animal {
fn get_number_of_legs(&self) -> u32 {
self.number_of_legs
}
}
struct Cat {
animal: Animal,
sound: String,
}
struct Dog {
animal: Animal,
sound: String,
}
impl InfoAnimal for Cat {
fn say_hello() -> String {
"Miawww".to_string()
}
fn get_number_of_legs(&self) -> u32 {
self.animal.number_of_legs
}
}
impl InfoAnimal for Dog {
fn say_hello() -> String {
"Waffff".to_string()
}
fn get_number_of_legs(&self) -> u32 {
self.animal.number_of_legs
}
}
We must add the Animal member variable to all structs (Cat,Dog), and implement the "get_number_of_legs" function for each of them.
So imagine the hassle if you have very complicated structures with several layers of inheritance
Assuming you're a masochist who likes to bang out thousands of lines of code for free (just kidding ) , you're going to tell me it's a price to pay, but in any case the compiler will make the necessary optimizations.
But according to some tests I've carried out, the assembly code generated isn't as optimized as if we had true inheritance. (and whatever the power of the optimizer, a language must not be 100% optimizer-dependent.)
code with inheritance simulation :
struct Animal {
number_of_legs: u32,
is_domestic: bool,
}
impl Animal {
fn get_number_of_legs(&self) -> u32 {
self.number_of_legs
}
}
struct Cat {
animal: Animal,
sound: String,
}
impl Cat {
fn get_number_of_legs(&self) -> u32 {
self.animal.number_of_legs
}
}
code if we had the inheritance :
struct Cat extends Animal {
sound: String,
}
if we were to get as close as possible, it will generate background code like this :
struct Cat {
number_of_legs: u32,
is_domestic: bool,
sound: String,
}
impl Cat {
fn get_number_of_legs(&self) -> u32 {
self.number_of_legs
}
}
It would be really interesting and useful to have the extends keyword, which allows structs to be merged.
struct Cat **extends** Animal {
sound: String,
}
or
#[fusion(Animal)]
struct Cat {
sound: String,
}
I fully understand that this is easy to say theoretically, but extremely difficult to apply in practice, because you have to manage polymorphism while remaining consistent with the concept of "traits".
The "trait" concept is very powerful and practical, but it doesn't answer this kind of problem.
For example in GoLang, they have "Struct Embedding", it's not inheritance, but it allows you to simulate it partially.
I think the solution proposed by Go is a good compromise, it just lacks a keyword that defines whether or not you want to expose the methods of the fields.
in any case, thank you for taking the time to read my post, and I'd like the interactions with this post to be reflections to find a good compromise rather than messages saying "no inheritance, troubleshoot with traits".