I am studying multiple inheritance, and I read that it is considered bad design.
I created an example where multiple inheritance would be useful, and I have not found a way to rewrite it to remove multiple inheritance.
Furthermore, many languages do not support multiple inheritance and a new design is needed.
The 'Animal' class implements many things that all animals do.
The 'AquaticAnimal' class implements everything about water.
The 'TerrestrialAnimal' class implements everything about animal on land.
The 'Amphibious' class was created for animals that can do everything that 'AquaticAnimal' and 'TerrestrialAnimal' can do.
The application needs to use 'Amphibious' animals in the classes: Zoo, Aquarius, Plains and AmphibiousRace.
Despite virtual inheritance, the diamond problem continues, because calling Amphibious.eat() will call Animal.eat() twice and it will lead to inconsistent state.
It is not a real programming language, but it is like Java/C++.
class Animal{
private:
Place birthplace;
String name;
List likesToEat;
Stomach stomach;
public:
virtual void growl(){ ... }
virtual int eat(Food food){
... test if likes
... many operations
chew()
...
stomach.fill(food);
}
}
class FlyingAnimal extends Animal {
private:
Wings wings;
public:
void fly(){ ... wings.move(); ... }
}
class AquaticAnimal extends Animal{
private:
Flipper flipper;
public:
void swim(){ ... flipper.move(); ... }
int eat(Food food){
int x = Animal.eat(food);
... use x
flipper.nourish(food);
}
}
class TerrestrialAnimal extends Animal{
private:
Legs legs;
public:
void run(){ ... legs.move(); ... }
int eat(Food food){
int x = Animal.eat(food);
... use x
legs.nourish(food);
}
}
class Amphibious extends AquaticAnimal, TerrestrialAnimal{
public:
int eat(Food food){
AquaticAnimal.eat(food);
TerrestrialAnimal.eat(food);
//PROBLEM: Animal.eat() will be called twice.
}
}
//------------------------------------------
class Zoo {
public:
void add/remove(Animal a);
void feed(Animal a);
void show(Animal a);
}
class Aquarius {
public:
void add/remove(AquaticAnimal a);
}
class Plains {
public:
void add/remove(TerrestrialAnimal a);
}
class HighPeaks {
public:
void add/remove(FlyingAnimal a);
}
class AmphibiousRace {
public:
void add/remove(Amphibious a);
void enterIntoLake(Amphibious a);
void exitFromLake(Amphibious a);
}