• Post Reply Bookmark Topic Watch Topic
  • New Topic

multiple inheritance

Koteswara Rao Chebrolu
Posts: 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello Friends ,
i am new to JAVA,
could plz any one tell me, "why java is not supporting multiple inheritence directly" ?

[ March 01, 2004: Message edited by: Koteswara Rao Chebrolu ]
Mark Spritzler
Posts: 17290
IntelliJ IDE Mac Spring
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Welcome to JavaRanch. Unfortunately this is the Servlets forum. Your question is more appropriate in the Java in General (Beginner's) forum. I am going to move this thread to that forum.
fred rosenberger
lowercase baba
Posts: 12340
Chrome Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I don't know the "official" answer, but i do know this...
multiple inheritance is a pain in the... rear. If i have two parent classes that both have a toString() method, which should the child class use?
Java does use interfaces, which (kind of) let you do multiple inheritence, but not really.
my (granted not very helpful) 2cents worth.
sever oon
Ranch Hand
Posts: 268
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Multiple inheritance is not available in Java because it's a complicated and unnecessary solution to a problem. There is never a reason to prefer it over other more simple and clear solutions.
We'll start with the Dreaded Diamond problem.

What is the result of running SubSub's main() method? Will new SubSub().foo() result in "foo base" or "foo sub1"? Because SubSub extends both Sub1 and Sub2, it inherits Sub1's implementation of foo(), but because it extends Sub2, it also inherits *its* implementation of foo() as well (which Sub2 itself inherits from Base).
If you draw out the inheritance structure described above, you see the Dreaded Diamond problem of multiple inheritance. For languages that support MI, they have some way of solving this problem, either by picking one or the other, or by forcing the programmer to address it if there are multiple conflicting implementations.
You might say, wait, how often would this happen in Java if Java allowed MI? Just do a good design and don't let it happen! This is nearly impossible, because every class in Java is a subclass of java.lang.Object, all MI would result in this diamond, meaning that you cannot override any of Object's methods in classes that are to be used in an MI hierarchy. Some say the Java compiler could just recognize the conflict and force you to implement it either as:


I think this just transfers a lot of code bloat--one of the main selling points of MI is that it removes code bloat, so by introducing it it's working at cross-purposes with one of its stated goals.
Now consider a situation where it seems like a good idea to use MI, though, and question whether it cannot be done another, better way. Let's say you have classes Base1, Base2, and Base3 and you want to implement a classes Sub1, Sub2, and Sub3, each of which extends all of Base1, Base2, and Base3. In other words, if MI were an option, you could write:

What are the advantages of inheritance that you're trying to exploit by using MI here? There are a few big ones as far as I can see. When a class Sub extends another class Base:
  • objects of type Sub can be polymorphically treated as objects of type Base.
  • changes in method bodies in Base are *automatically* inherited by Sub, without having to update code in Sub.
  • if ref instanceof Sub == true, then ref instanceof Base == true as well.
  • Sub can override methods in Base

  • If a class Sub extends another class Base, then it meets all of the above criteria.
    Many people will probably reply to your question with the age-old answer, "Prefer aggregation to inheritance". It's true that you can draft a good design that will use aggregation in place of MI in most cases. However, in some cases, you might prefer MI because you want *all* of the above conditions to be true for Sub wrt Base1, Base2, and Base3. In those cases, simple aggregation will not get you that:

    In the above example... Can Sub be polymorphically treated as type Base? No. Are changes to foo() in Base1 automatically available to Sub without changing code in Sub? Yes. If some reference (ref instanceof Sub) == true, will (ref instanceof Base) == true? No. And finally, can Sub "override" methods of Base? Kind of--not actually "overriding" technically, but if I were to replace Sub's implementation of foo() with some other code, then that would approximate overriding Base's foo().
    Still, though, we're left sorely lacking on the first and third points, so in cases where those points are important aggregation alone isn't quite cutting it. Worse yet, what if I want to simulate MI in not just one subclass, but three: Sub1, Sub2, and Sub3? Do I have to write this aggregation code for each and every one of them? Isn't there some way we can provide an easy means for other developers to extend these three Base classes easily? Is there any way we get all of the advantages of direct MI in Java through design?
    I believe yes, but it requires separating Base1, Base2, and Base3's contracts (APIs) from their implementation classes. Once you do this, you can provide a single class that serves as a code container for all of the aggregation code. You can look at this as a sort of manual way to do MI for the Java compiler:

    Notice I've marked the AbstractSub class protected (at the class level). This is because I don't ever want code in the system to deal with objects polymorphically as type AbstractSub--instead, all subclassees of AbstractSub can be polymorphically treated as type Sub, the interface type (AbstractSub's docs should spell this out explicitly). AbstractSub therefore is specified only for one purpose: to act as a code container for subclasses to inherit all of that messy aggregation code. This is why I provided the Sub interface above, even though it is not strictly necessary (it could be deleted and AbstractSub could have simply implemented Base1, Base2, and Base3 instead): it provides a way for other code to treat Sub1, Sub2, and Sub3 polymorphically without having to decide between Base1, Base2, and Base3. What if a client wants to create an array of subs and call foo(), bar(), and baz() on each element without a bunch of messy typecasting? Can't be done without the Sub interface--since that's there, though, one could simply write:

    Now let's go through the check list to see if we've hit all the points:
    Can Sub1, Sub2, and Sub3 all be treated polymorphically as type Base1, Base2, and Base3? Yes.
    Will changes to method bodies in any of the Base classes be automatically inherited by Sub1, Sub2, and Sub3? Yes.
    If ref instanceof Sub == true, is (ref instanceof Base1 && ref instanceof Base2 && ref instanceof Base3) == true? Yes.
    If Sub1, Sub2, or Sub3 provide foo(), bar(), or baz(), will these methods override the Base implementations? Yes.
    Because all of these conditions are satisfied, we can consider any class that extends AbstractSub as having multiply inherited from Base1, Base2, and Base3 in every way.
    One of these days, when I get time I'm going to see if there's a good way to implement this MI stuff using Java 1.5's new metadata facility. Probably not very useful, but loads of fun I'm sure.
    [ March 01, 2004: Message edited by: sever oon ]
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!