views:

3221

answers:

13

Is it a good concept to use or I can do other things in place of this?

+10  A: 

See w:Multiple Inheritance.

Multiple inheritance has received criticism and as such, is not implemented in many languages. Criticisms includes:

  • Increased complexity
  • Semantic ambiguity often summarized as the diamond problem.
  • Not being able to explicitly inherit multiple times from a single class
  • Order of inheritance changing class semantics.

Multiple inheritance in languages with C++/Java style constructors exacerbates the inheritance problem of constructors and constructor chaining, thereby creating maintenance and extensibility problems in these languages. Objects in inheritance relationships with greatly varying construction methods are hard to implement under the constructor chaining paradigm.

Modern way of resolving this to use interface (pure abstract class) like COM and Java interface.

I can do other things in place of this?

Yes, you can. I am going to steal from GoF.

  • Program to an Interface, not an Implementation
  • Prefer composition over inheritance
eed3si9n
+15  A: 

There's no reason to avoid it and it can be very useful in situations. You need to be aware of the potential issues though.

The biggest one being the diamond of death:

class GrandParent;
class Parent1 : public GrandParent;
class Parent2 : public GrandParent;
class Child : public Parent1, public Parent2;

You now have two "copies" of GrandParent within Child.

C++ has thought of this though and lets you do virtual inheritence to get around the issues.

class GrandParent;
class Parent1 : public virtual GrandParent;
class Parent2 : public virtual GrandParent;
class Child : public Parent1, public Parent2;

Always review your design, ensure you are not using inheritance to save on data reuse. If you can represent the same thing with composition (and typically you can) this is a far better approach.

billybob
A: 

You can use composition in preference to inheritance.

The general feeling is that composition is better, and it's very well discussed.

Ali A
+1  A: 

You shouldn't "avoid" multiple inheritance but you should be aware of problems that can arise such as the 'diamond problem' ( http://en.wikipedia.org/wiki/Diamond_problem ) and treat the power given to you with care, as you should with all powers.

duncan
+1  A: 

Uses and Abuses of Inheritance.

The article does a great job of explaining inheritance, and it's dangers.

csexton
+2  A: 
CMS
This is a bad example, because a copier should be composed of a scanner and a printer, not inherit from them.
Svante
+2  A: 

Aside from the reference to specifically C++, this question seems to be a duplicate:

What is the exact problem with multiple inheritance?

At the very least, I believe the answers there should shed some light on this question.

Scott Saad
+1  A: 

Beyond the diamond pattern, multiple inheritance tends to make the object model harder to understand, which in turn increases maintenance costs.

Composition is intrinsically easy to understand, comprehend, and explain. It can get tedious to write code for, but a good IDE (it's been a few years since I've worked with Visual Studio, but certainly the Java IDEs all have great composition shortcut automating tools) should get you over that hurdle.

Also, in terms of maintenance, the "diamond problem" comes up in non-literal inheritance instances as well. For instance, if you have A and B and your class C extends them both, and A has a 'makeJuice' method which makes orange juice and you extend that to make orange juice with a twist of lime: what happens when the designer for 'B' adds a 'makeJuice' method which generates and electrical current? 'A' and 'B' may be compatible "parents" right now, but that doesn't mean they will always be so!

Overall, the maxim of tending to avoid inheritance, and especially multiple inheritance, is sound. As all maxims, there are exceptions, but you need to make sure that there is a flashing green neon sign pointing at any exceptions you code (and train your brain so that any time you see such inheritance trees you draw in your own flashing green neon sign), and that you check to make sure it all makes sense every once in a while.

Tom Dibble
+1  A: 

The most important thing about multiple inheritance is figuring out whether you really NEED it or not. If you don't need it, then the problems aren't worth it at all. Why would you need multiple inheritance? The ONLY reason is if the new object MUST be used as ALL of the base classes. This is going to depend on your application and framework, but I've found over the years that this usually occurs far less than you'd think.

Many of the times that I've used multiple inheritance have turned out to be mistakes on my part - I was not thinking about how the object was to be used, and ended up creating a maintenance headache for myself.

Michael Kohne
A: 

it takes 4/8 bytes per class involved. (One this pointer per class).

This might never be a concern, but if one day you have a micro data structure which is instanced billions of time it will be.

Ronny
Sure about that? Typically, any serious inheritance will require a pointer in each class member, but does that necessarily scale with classes inherited? More to the point, how many times have you had billions of teeny data structures?
David Thornley
+7  A: 

From an interview with Bjarne Stroustrup:

People quite correctly say that you don't need multiple inheritance, because anything you can do with multiple inheritance you can also do with single inheritance. You just use the delegation trick I mentioned. Furthermore, you don't need any inheritance at all, because anything you do with single inheritance you can also do without inheritance by forwarding through a class. Actually, you don't need any classes either, because you can do it all with pointers and data structures. But why would you want to do that? When is it convenient to use the language facilities? When would you prefer a workaround? I've seen cases where multiple inheritance is useful, and I've even seen cases where quite complicated multiple inheritance is useful. Generally, I prefer to use the facilities offered by the language to doing workarounds

Nemanja Trifunovic
+9  A: 

Multiple inheritance smells, which means that usually, it was done for bad reasons, and it will blow back in the face of the maintainer.

Summary

  1. Consider composition of features, instead of inheritance
  2. Be wary of the Diamond of Dread
  3. Consider inheritance of multiple interfaces instead of objects
  4. Sometimes, Multiple Inheritance is the right thing. If it is, then use it.
  5. Be prepared to defend your multiple-inherited architecture in code reviews

1. Perhaps composition?

This is true for inheritance, and so, it's even more true for multiple inheritance.

Does your object really needs from another? A Car do not need to inherit from an Engine to work, nor from a Wheel. A Car has an Engine and four Wheel.

If you use multiple inheritance to resolve this problem instead of composition, then you did something wrong.

2. The Diamond of Dread

Usually, you have a class A, and then B and C both inherit from A. And don't ask me why, someone then decides that D must inherit both from B and C.

I encountered this kind of problem twice in 8 eights years, and it is amusing to see because of:

  1. How much a mistake it was from the beginning (In both cases, D should not have inherited from both B anc C), because this was bad architecture (in fact, C should not have existed at all...)
  2. How much maintainers were paying for that, because in C++, the parent class A was present twice in its grandchild class D, and thus, updating one parent field A::field meant either updating them twice (through B::field and C::field), or have something goes silently wrong and crash, later (new a pointer in B::field, and delete C::field...)

Using the keyword virtual in C++ void the double layout described above, but anyway, you're probably doing something wrong...

In Object hierarchy, you should keep the hiearchy as a Tree (a node has ONE parent), not as a graph.

3. Interfaces

Multiple inheritance of zero or one concrete classe, and zero or more interfaces is usually Ok, because you won't encounter the Diamond of Dread described above. In fact, this is how things are done in Java.

Usually, what you mean when C inherits from A and B is that users can use C as if it was a A, and/or as if it was a C.

In C++, an interface is an abstract class which has:

  1. all its method declared pure virtual (suffixed by = 0)
  2. no member variables

The Multiple inheritance of zero to one real object, and zero or more interfaces is not considered "smelly" (at least, not as much)

4. Do you really need Multiple Inheritance?

Sometimes, yes.

Usually, your C class is inheriting from A and B, and A and B are two unrelated objects (i.e. not in the same hierarchy, nothing in common, different concepts, etc.).

For example, you could have a system of Nodes with X,Y,Z coordinates, able to do a lot of geometric calculations (perhaps a point, part of geometric objects) and each Node is an Automated Agent, able to communicate with other agents.

Perhaps you already have access to two libraries, each with its own namespace (another reason to use namespaces... But you use namespaces, don't you?), one being "geo" and the other bing "ai"

So you have your own "own::Node" derive both from "ai::Agent" and "geo::Point".

This is the moment when you should ask yourself if you should not use composition instead. If "own::Node" is really really both a "ai::Agent" and a "geo::Point", then composition would not do.

Then you'll need multiple inheritance, having your "own::Node" communicate with other agents according to their position in a 3D space.

(You'll note that ai::Agent and geo::Point are completely, totally, fully UNRELATED... This is what reduces drastically the danger of multiple inheritance)

5. So, should I do Multiple Inheritance?

Most of the time, no. MI is not the right tool, even if it seems it will work.

But sometimes, yes. And at that time, nothing will work better than MI, and you won't have a Diamond of Dread, and your object is really both its parent.

But because MI is smelly, be prepared to defend your architecture in code reviews (and defending it is a good thing, because if you're not able to defend it, then you should not do it).

paercebal
+2  A: 

Public inheritance is an IS-A relationship, and sometimes a class will be an type of several different classes, and sometimes it's important to reflect this.

"Mixins" are also sometimes useful. They are generally small classes, usually not inheriting from anything, providing useful functionality.

As long as the inheritance hierarchy is fairly shallow (as it should almost always be), and well managed, you're unlikely to get the dreaded diamond inheritance. The diamond isn't a problem with all languages that use multiple inheritance, but C++'s treatment of it is frequently awkward and sometimes puzzling.

While I've run into cases where multiple inheritance is very handy, they're actually fairly rare. This is likely because I prefer to use other design methods when I don't really need multiple inheritance. I do prefer to avoid confusing language constructs, and it's easy to construct inheritance cases where you have to read the manual really well to figure out what's going on.

David Thornley
+1: Mixins are quite useful.
cdleary