Tuesday, August 20, 2013

Why multiple inheritance is bad?

I'm not against multiple inheritance. Anything can be a tool in the right hands, and multiple inheritance is a such tool. But it is common question: why multiple inheritance is not suitable for most situations? And really it is not very good. Almost any problem could be solved using single inheritance, interfaces or composition. Many languages deny multiple inheritance, and here is my point of view on this problem.

Imagine, we have two classes "cat" and "duck" :)



Cat and duck are two classes, they definetely derived from some "animal" class, but we talk about this problem later. They are happy and function normally, until the developer decides to make the third class. And this class supposed to act as a cat and duck simultaneously. And the multiple inheritance is chosen as the solution. But lets put programming languages aside and think about it. Object oriented programming relies on the real world logic, what will happen, if something will be derived from cat and duck at the same time? I guess this is the answer:



Now we have a terrible creature. And it lives!

In OOP the class is answering the question: "what am i?" and it is easy to answer this question for "cat" and "duck" classes, but what is the answer for the class derived from both of those two? It will be: "I'm catduck. And developer needs me." Once again, multiple inheritance is a tool, but it can be misused, and usually it is misused.

One of the very (very and very) popular "problems" of multiple inheritance is diamond problem (and it can be avoided, by the way). But i will draw it regardless, just because i feel like i want to draw something:

Here base class "animal" has method eat() and both "cat" and "duck" classes override this method. So the cat and duck can eat, but in "catduck" class method eat() is not overriden, and now there is ambiguity: which method will be used, if we call eat() for instance of our class which derived from cat and duck? Well, sometimes multiple inheritance leads to even bigger problems.

Alright, but how to avoid multiple inheritance, and still have the object, which acts like the cat and duck at the same time? First solution is to put cat and duck in the cage:

Now we have third object - "cage", and if we want cat behaviour - we will release cat, if we need duck - there is duck inside. And we can define some methods, specific only for cage itself in this class. Good solution, but there is one more. Instead of having to create a monster we can make this monster to sign contract with us. This require some changes in the application architecture. For example, our cat can purr and we can pet it, and our duck can swim and quack. We need a creature, that can purr, quack, swim and we want to pet this thing. This is where interfaces take the stage:

Interface is answering the question "what can i do?". Basically, we create multiple interfaces, describing our cat and duck abilities, such as quack, purr, swim and so on. Both cat and duck will implement some of those interfaces. And we just tell our third class: "you will implement all, all those features, here, sign this contract". Now we implement all the needed interfaces in our "catduck" class and this allow us to get rid of multiple inheritance and to make application more flexible.

That's pretty much it. Composition and interfaces can be a good replacement for multiple inheritance. But sometimes, you just need to create a "monster". :)

Yep, i can't draw.

No comments :

Post a Comment