I was reading up about something and I realised I don't really understand Inheritance and whats so wrong with multiple inheritance. Why has Java not implemented it? I mean I have a computer science degree, so I know what it is, but if someone asked me to explain why, i would fumble. So I decided to burn some trees and ask chatgpt.
Inheritance is a mechanism where the child class acquires properties and methods of its parent class.
For example,
#include <iostream>
using namespace std;
// Base class
class Animal {
public:
void eat() {
cout << "This animal eats food." << endl;
}
};
// Derived class
class Dog : public Animal {
public:
void bark() {
cout << "The dog barks." << endl;
}
};
int main() {
Dog d;
d.eat(); // Inherited from Animal
d.bark(); // Defined in Dog
}
The above example is a classic example of inheritance in cpp. But when I saw this, I realised I didn't actually understand what exactly is meant when we say "the child class acquires properties and methods of its parent class", does it get copied? does it get referenced? So I dived a little deeper and understood Inheritance can be understood differently based on which language you're referencing.
Let's take a different example in C++:
class Animal {
public:
int age;
};
class Dog : public Animal {
public:
int weight;
};
int main() {
Dog d;
Animal* a = &d;
}
Here, Dog d in memory would look something like this:
Address: 0x1000 [ age ] ← Animal base subobject
Address: 0x1004 [ weight ] ← Dog part
This means that when we create an object of a child class, the first few bytes are occupied by the copied methods and properties of its parent class.
This clears up two very important things,
Animal* a = &d; very easy to compute as the offset in memory is already 0.Now let's understand what multiple inheritance is. A class inheriting from more than one base class.
A
/ \
B C
\ /
D
class A {
int x;
};
class B : public A { };
class C : public A { };
class D : public B, public C { };
In memory D:
+----------------+
| B subobject |
| +------------+|
| | A::x ||
| +------------+|
+----------------+
| C subobject |
| +------------+|
| | A::x ||
| +------------+|
+----------------+
Can you see why multiple inheritance is problematic now?
Every time we create an object of D, we get two copies of x! So when we try to reference it with D.x the compiler throws an error saying the operation we are trying to perform is ambiguous. It doesn't know which x we want.
We can either resolve this by specifying which x we want like so:
d.B::x;
d.C::x;Or we can use virtual inheritance. Instead of making two separate copies of A, we a single copy, while B and C hold pointers to that copy. This makes the object layout more complex and often requires runtime pointer adjustment.
In memory D:
+----------------+
| B subobject |
| (pointer to A)|
+----------------+
| C subobject |
| (pointer to A)|
+----------------+
| A subobject | <-- SINGLE shared A
| A::x |
+----------------+
Unlike C++, Python does not copy sub-objects in memory in the same way, instead it resolves attributes dynamically through MRO. It is the ordered list of classes that Python searches when resolving attributes.
For example,
class A:
x= 5
class B(A): pass
class C(A): pass
class D(B, C): passHere, when we try accessing D.x, python checks in D.__mro__ for the class list. In this case it would return (D, B, C, A, object). So it would first search in D, if D.__dict__ does not have x present in it, it will go to B. Again search for x in B.__dict__, till it reaches A and finds x.
Java avoided multiple inheritance of classes not because it’s impossible, but because it complicates object structure and reasoning.