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:
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.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?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 aA
andB
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
Java.Lang.Runtime Exception "Cannot Run Program"
Serial Port Identification with Java on Ubuntu
Java - Io Bound Thread - 1:1 Threading Model
Java I/O VS. Java New I/O (Nio) with Linux Nptl
Ioexception: Too Many Open Files
Using Visualvm to Connect to a Remote Jstatd Instance Through a Firewall
Force Jvm to Do All Io Without Page Cache (E.G. O_Direct)
Too Many Open Files Error But Lsof Shows a Legal Number of Open Files
Problems Installing Java Ee Sdk on Linux
Wireless API for Linux in C or Java
Best Way to Daemonize Java Application on Linux
How to Implement Basic Authentication with Glassfish
Jfilechooser and Browsing Networked MAChines
How to Build Netty-Transport-Native-Epoll-4.0.32.Final-Linux-X86_64.Jar
Android - Span_Exclusive_Exclusive Spans Cannot Have a Zero Length