Java Multiple Inheritance

Java Multiple Inheritance

You could create interfaces for animal classes (class in the biological meaning), such as public interface Equidae for horses and public interface Avialae for birds (I'm no biologist, so the terms may be wrong).

Then you can still create a

public class Bird implements Avialae {
}

and

public class Horse implements Equidae {}

and also

public class Pegasus implements Avialae, Equidae {}

Adding from the comments:

In order to reduce duplicate code, you could create an abstract class that contains most of the common code of the animals you want to implement.

public abstract class AbstractHorse implements Equidae {}

public class Horse extends AbstractHorse {}

public class Pegasus extends AbstractHorse implements Avialae {}

Update

I'd like to add one more detail. As Brian remarks, this is something the OP already knew.

However, I want to emphasize, that I suggest to bypass the "multi-inheritance" problem with interfaces and that I don't recommend to use interfaces that represent already a concrete type (such as Bird) but more a behavior (others refer to duck-typing, which is good, too, but I mean just: the biological class of birds, Avialae). I also don't recommend to use interface names starting with a capital 'I', such as IBird, which just tells nothing about why you need an interface. That's the difference to the question: construct the inheritance hierarchy using interfaces, use abstract classes when useful, implement concrete classes where needed and use delegation if appropriate.

How to explain multiple inheritance in Java

Multiple inheritance is about multiple-direct-inheritance.

A single class class can't have two immediate parent classes. It can have a grandparent class, though.

A extends B and B extends C, is not the same as A extends both B and C.

The reason this is disallowed is for simplicity when you have a case like:

A extends both B and C

B extends D

C extends D

If you had such a case, and then you had this code:

A a = new A();
a.someAbstractOrVirtualMethodOnD();

... are you talking about the B implementation of someAbstractOrVirtualMethodOnD(), or the C implementation of that same method? Which should get called? (Hint: there isn't a great answer)

So, Java bans it.

Note, you can get something much like multiple inheritance if you implement multiple interfaces. But since there is only one concrete implementation, there is no confusion as to what gets called.

Why is Multiple Inheritance not allowed in Java or C#?

The short answer is: because the language designers decided not to.

Basically, it seemed that both the .NET and Java designers did not allow multiple inheritance because they reasoned that adding MI added too much complexity to the languages while providing too little benefit.

For a more fun and in-depth read, there are some articles available on the web with interviews of some of the language designers. For example, for .NET, Chris Brumme (who worked at MS on the CLR) has explained the reasons why they decided not to:

  1. Different languages actually have different expectations for how MI
    works. For example, how conflicts are
    resolved and whether duplicate bases
    are merged or redundant. Before we can
    implement MI in the CLR, we have to do
    a survey of all the languages, figure
    out the common concepts, and decide
    how to express them in a
    language-neutral manner. We would also
    have to decide whether MI belongs in
    the CLS and what this would mean for
    languages that don't want this concept
    (presumably VB.NET, for example). Of
    course, that's the business we are in
    as a common language runtime, but we
    haven't got around to doing it for MI
    yet.

  2. The number of places where MI is truly appropriate is actually quite
    small. In many cases, multiple
    interface inheritance can get the job
    done instead. In other cases, you may
    be able to use encapsulation and
    delegation. If we were to add a
    slightly different construct, like
    mixins, would that actually be more
    powerful?

  3. Multiple implementation inheritance injects a lot of complexity into the
    implementation. This complexity
    impacts casting, layout, dispatch,
    field access, serialization, identity
    comparisons, verifiability,
    reflection, generics, and probably
    lots of other places.

You can read the full article here.

For Java, you can read this article:

The reasons for omitting multiple
inheritance from the Java language
mostly stem from the "simple, object
oriented, and familiar" goal. As a
simple language, Java's creators
wanted a language that most developers
could grasp without extensive
training. To that end, they worked to
make the language as similar to C++ as
possible (familiar) without carrying
over C++'s unnecessary complexity
(simple).

In the designers' opinion, multiple
inheritance causes more problems and
confusion than it solves. So they cut
multiple inheritance from the language
(just as they cut operator
overloading). The designers' extensive
C++ experience taught them that
multiple inheritance just wasn't worth
the headache.

Why does Java not allow multiple inheritance but does allow conforming to multiple interfaces with default implementations

Things are not so simple.

If a class implements multiple interfaces that defines default methods with the same signature the compiler will force you to override this method for the class.

For example with these two interfaces :

public interface Foo {
default void doThat() {
// ...
}
}

public interface Bar {
default void doThat() {
// ...
}
}

It will not compile :

public class FooBar implements Foo, Bar{
}

You should define/override the method to remove the ambiguity.

You could for example delegate to the Bar implementation such as :

public class FooBar implements Foo, Bar{    
@Override
public void doThat() {
Bar.super.doThat();
}
}

or delegate to the Foo implementation such as : :

public class FooBar implements Foo, Bar {
@Override
public void doThat() {
Foo.super.doThat();
}
}

or still define another behavior :

public class FooBar implements Foo, Bar {
@Override
public void doThat() {
// ...
}
}

That constraint shows that Java doesn't allow multiple inheritancy even for interface default methods.


I think that we cannot apply the same logic for multiple inheritances because multiples issues could occur which the main are :

  • overriding/removing the ambiguity for a method in both inherited classes could introduce side effects and change the overall behavior of the inherited classes if they rely on this method internally. With default interfaces this risk is also around but it should be much less rare since default methods are not designed to introduce complex processings such as multiple internal invocations inside the class or to be stateful (indeed interfaces cannot host instance field).
  • how to inherit multiple fields ? And even if the language allowed it you would have exactly the same issue as this previously quoted : side effect in the behavior of the inherited class : a int foo field defined in a A and B class that you want to subclass doesn't have the same meaning and intention.

How to avoid multiple inheritance?

Java8 introduced default and static methods for interfaces. To a certain degree, that allows for multiple inheritance. But most likely, the correct solution would be to rework your design.

You see, inheritance is not about code re-use. It is about creating useful abstractions; and make good use of polymorphism for example.

In your case: maybe those functionalities could/should be put into smaller interfaces; and then segregated into their own, independent classes. And then you use composition of objects instead of inheritance to build the thing you need.

Abstract classes and Multiple Inheritance

This is not allowed because you can do more than this with abstract classes. It wouldn't make sense to allow multiple inheritance, provided you only used an abstract class when you could have used an interface.

It is simpler to only use abstract classes for things you can't do with an interface, in which case you wouldn't be able to use two abstract parent classes.

Note: with Java 8 there is less you can't do with an interface, you can have public instance and static methods with implementations.

In Java 9 you will be able to have private methods in interfaces ;)

Multiple Inheritance in Java since All classes extend from Object class?

All classes extend form Object, either implicitly or explicitly, directly or indirectly, the whole class hierarchy in Java ends up pointing at Object, which is at the root. For instance, when you write this:

public class MyClass extends Object {

Is exactly the same as this:

public class MyClass {

And if we have this:

public class MySubClass extends MyClass {

Then MySubClass extends from MyClass which extends from Object. It's a transitive inheritance relationship, and it occurs in only one direction: at no point in the hierarchy it will be possible that a single class extends from more than one class - that's why we say that in Java we have single-inheritance (as opposed to: multiple-inheritance.)

Multiple Inheritance, using interface vs using composition in Java

Interfaces are not about inheriting behaviour. Make your class implement an interface if you want to let OTHERS know what your class is capable of, not to teach YOUR class how to do stuff.

If some library can do some interesting stuff to an object that has a getName() method, you cannot expect that it knows all the classes in the world that have this method, but you can make your class implement an interface that the library knows (say Named), which enforces this method is present.

From your perspective, it does not modify your class much, and your objects may still be vastly different from other Named objects. From that library's perspective, it makes your object usable.

To elaborate: if you only need access to specific methods that already exist in some other class, this is enough:

class Preference{
AA aa;
BB bb;

public int id() {
return aa.id();
}

public String name() {
return bb.name();
}
}

Your object will know how to say it's name and id (or will it? It's not really your object's name after all :) . But you will not, among other things, be able to add it to collection of AAs, BBs, AAInterfaces or BBInterfaces. It IS neither of them. It just acts like them. Depending on the needs it may or may not be enough.



Related Topics



Leave a reply



Submit