In an attempt to fully understand how to solve Java's multiple inheritance problems I have a classic question that I need clarified.
Lets say I have class Animal
this has sub classes Bird
and Horse
and I need to make a class Pegasus
that extends from Bird
and Horse
since Pegasus
is both a bird and a horse.
I think this is the classic diamond problem. From what I can understand the classic way to solve this is to make the Animal
, Bird
and Horse
classes interfaces and implement Pegasus
from them.
I was wondering if there was another way to solve the problem in which I can still create objects for birds and horses. If there was a way to be able to create animals also that would be great but not necessary.
The Java programming language supports multiple inheritance of type, which is the ability of a class to implement more than one interface. An object can have multiple types: the type of its own class and the types of all the interfaces that the class implements.
When one class extends more than one classes then this is called multiple inheritance. For example: Class C extends class A and B then this type of inheritance is known as multiple inheritance. Java doesn't allow multiple inheritance.
The reason behind this is to prevent ambiguity. Consider a case where class B extends class A and Class C and both class A and C have the same method display(). Now java compiler cannot decide, which display method it should inherit. To prevent such situation, multiple inheritances is not allowed in java.
Multiple inheritance is useful when a subclass needs to combine multiple contracts and inherit some, or all, of the implementation of those contracts. For example, the AmericanStudent class needs to inherit from both the Student class and the American class.
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 {}
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 {}
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.
There are two fundamental approaches to combining objects together:
The way this works is that you have an Animal object. Within that object you then add further objects that give the properties and behaviors that you require.
For example:
Now IFlier
just looks like this:
interface IFlier { Flier getFlier(); }
So Bird
looks like this:
class Bird extends Animal implements IFlier { Flier flier = new Flier(); public Flier getFlier() { return flier; } }
Now you have all the advantages of Inheritance. You can re-use code. You can have a collection of IFliers, and can use all the other advantages of polymorphism, etc.
However you also have all the flexibility from Composition. You can apply as many different interfaces and composite backing class as you like to each type of Animal
- with as much control as you need over how each bit is set up.
Strategy Pattern alternative approach to composition
An alternative approach depending on what and how you are doing is to have the Animal
base class contain an internal collection to keep the list of different behaviors. In that case you end up using something closer to the Strategy Pattern. That does give advantages in terms of simplifying the code (for example Horse
doesn't need to know anything about Quadruped
or Herbivore
) but if you don't also do the interface approach you lose a lot of the advantages of polymorphism, etc.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With