Java Multiple Inheritance
Asked Answered
P

17

172

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.

Preglacial answered 17/2, 2014 at 8:46 Comment(8)
I think you can create manually the classes and store them as members (composition instead of inheritance). With the Proxy (docs.oracle.com/javase/7/docs/api/java/lang/reflect/Proxy.html) class this might be an option, although you will need the interfaces too.Dorweiler
I like @GáborBakos solution, but the only downside is that it can not have a generic reference type.Hyman
@RAM then it should not extend Bird rather have behaviour which will enable it to take a flight. :D problem solvedFaker
Exactly. How about an interface CanFly. :-)Inhalant
I think this is the wrong approach. You have animals - Horses, Birds. And you have properties - Flying, Carnivore. A Pegasus is not a HorseBird it is a Horse that can fly. The properties should in interfaces. So public class Pegasus extends Horse implements Flying.Deepseated
I understand why you think it is wrong and does not adhere to the rules of biology and appreciate your concern but in regards to the program I need to build which actually has to do with banks this was the best approach for me. As I did not want to post my actual problems since that would be against the rules I changed the example a bit. Thanks though...Preglacial
@Preglacial Java 8 will allow interfaces with default methods, this will allow a limited kind of multiple inheritance. Java 8 is release mid marchPentane
A better rea llife example would be child which has mother and father, both extending individual with different attributes, then you can inherit both, a mix or only one of them (like sex attributes/behavior/Impl)Femmine
F
119

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.

Fungible answered 17/2, 2014 at 8:52 Comment(8)
Which ... is exactly what the OP says they know you can do in the Q.Stank
As Pegasus IS already a Horse (that flies), I think you could reuse more code if extends Horse and implements Avialae.Deste
I'm not sure, I haven't seen a Pegasus yet. However, in that case I'd prefer to use a AbstractHorse, that can also be used to build Zebras or other horse-like animals.Fungible
@MoritzPetersen If you really want to go into reusing abstractions and giving meaningful names, probably AbstractEquidae would be more suitable than AbstractHorse. It would be strange to have a zebra extend an abstract horse. Nice answer, by the way.Cuisse
Implementing duck-typing would involve a Duck class implementing Avialae, too?Rodomontade
Class Avialae appears to be the wrong class since Pegasus doesn't have the muscle mass to use the wings to fly. Based on the images I've seen I think that the class HeavenHost is more appropriate.Misbecome
I would also look closely at using "Inheritance by Composition" in this scenario. Some people have suggested you make this class inherit "Horse" so you can reuse some of its code, but I think that leads you down a slippery slope. Why extend horse and not bird? What happens when you have another animal that is like a Pegasus...and then another that is like that. You suddenly have a long chain of concrete classes that are tightly coupled by inheritance. With inheritance by composition you could stick with implementing multiple interfaces but not extend/couple these concrete classes!Butch
What about non-interface classes?Torero
E
91

There are two fundamental approaches to combining objects together:

  • The first is Inheritance. As you have already identified the limitations of inheritance mean that you cannot do what you need here.
  • The second is Composition. Since inheritance has failed you need to use composition.

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:

  • Bird extends Animal implements IFlier
  • Horse extends Animal implements IHerbivore, IQuadruped
  • Pegasus extends Animal implements IHerbivore, IQuadruped, IFlier

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.

Eudoca answered 17/2, 2014 at 9:35 Comment(7)
A similar alternative might also be using type classes, although those are not so natural to use in Java (you have to use converter methods and so on), this intro might be useful to get the idea: typeclassopedia.bitbucket.orgDorweiler
This is a much better solution then the approach recommended in the accepted answer. For example, if I later want to add "beak color" to the Bird interface, I've got a problem. Pegasus is a composite, taking elements from horses and birds but neither fully horse nor bird. Using composition makes perfect sense in this scenario.Veneaux
But getFlier() has to be reimplemented for each and every kind of bird.Fiddlefaddle
@LifeH2O getFlier() can either be implemented in the Bird abstract class or it needs implementing in each kind of bird. Either way it's a very simple method though. (I agree repeated code is bad but this is about as minimal as a repeat can get). Another option is to use Generics and have Animal provide a <T>T getComponent(Class<T>clazz) method that returns a component matching the specified class from an internal collection of components.Eudoca
@TimB It is simple only for a single and simple function like above. I have some classes e.g. person. Than there are different kind of engineers and a few different kind of teachers. All kind of teachers inherit some similarities and all kind of engineers do the same. How can I make someone a Person and some Engineer without rewriting everything which each engineer share? Using generics is too specific.Fiddlefaddle
@LifeH2O Split them up into blocks of shared functionality then give them that. i.e. you might have MathsTeacher and EnglishTeacher both inheriting Teacher, ChemicalEngineer, MaterialsEngineer etc inherit Engineer. Teacher and Engineer both implement Component. The Person then just has a list of Components, and you can give them the right Components for that Person. i.e. person.getComponent(Teacher.class), person.getComponent(MathsTeacher.class), etc.Eudoca
This is the best answer. As a rule of thumb, inheritance represents "is" and an interface represents "can." A Pegasus IS an Animal that can Fly and Walk. A Bird is an Animal that can Fly. A Horse is an Animal that can Walk.Fabricant
P
45

I have a stupid idea:

public class Pegasus {
    private Horse horseFeatures; 
    private Bird birdFeatures; 

   public Pegasus(Horse horse, Bird bird) {
     this.horseFeatures = horse;
     this.birdFeatures = bird;
   }

  public void jump() {
    horseFeatures.jump();
  }

  public void fly() {
    birdFeatures.fly();
  }
}
Periosteum answered 17/2, 2014 at 9:9 Comment(7)
It will work, but I don't like that kind of approach (Wrappper) because then it seems Pegasus HAS a horse, instead it IS a horse.Deste
Thank you. I couldn’t help myself posting the idea. I kinda know it is stupid, but I did not see WHY it is stupid...Periosteum
It's almost like an unrefinded version of the composition approach from Tim B's answer.Preussen
This is more or less the accepted way to do it, though you should also have something like IJumps with a "jump" method that is implemented by Horse and Pegasus and IFlies with a "fly" method that is implemented by Bird and Pegasus.Inviting
This is one of the better approaches, particularly alongside @Stephan and @MatsT's points. You are completely using composition, but it should be combined with interface inheritance to give it the appropriate code contract. Java 8 will present another way to solve this uncommon--yet real--issue by providing default methods in interfaces, but limiting you to no access to fields (as it is an interface).Mcpeak
This could cause issues if someone passes weird Horse or Bird instances to the constructor, or uses those instances to go inside the Pegasus when they shouldn't.Polar
@Pablo no, a Pegasus HAS horseFeatures and HAS birdFeatures. +1 for the answer because it keeps the code simple, unlike the clunkier, class-spawning, proper Java solutions.Deadbeat
F
26

May I suggest the concept of Duck-typing?

Most likely you would tend to make the Pegasus extend a Bird and a Horse interface but duck typing actually suggests that you should rather inherit behaviour. As already stated in the comments, a pegasus is not a bird but it can fly. So your Pegasus should rather inherit a Flyable-interface and lets say a Gallopable-interface.

This kind of concept is utilized in the Strategy Pattern. The given example actually shows you how a duck inherits the FlyBehaviour and QuackBehaviour and still there can be ducks, e.g. the RubberDuck, which can't fly. They could have also made the Duck extend a Bird-class but then they would have given up some flexibility, because every Duck would be able to fly, even the poor RubberDuck.

Frobisher answered 17/2, 2014 at 9:17 Comment(0)
B
19

Technically speaking, you can only extend one class at a time and implement multiple interfaces, but when laying hands on software engineering, I would rather suggest a problem specific solution not generally answerable. By the way, it is good OO practice, not to extend concrete classes/only extend abstract classes to prevent unwanted inheritance behavior - there is no such thing as an "animal" and no use of an animal object but only concrete animals.

Biotin answered 17/2, 2014 at 8:55 Comment(0)
E
15

In Java 8 and later, you could use default methods to achieve a sort of C++-like multiple inheritance. You could also have a look at this tutorial which shows a few examples that should be easier to start working with than the official documentation.

Experimentation answered 17/2, 2014 at 10:3 Comment(2)
Be aware though that if your Bird and Horse both have a default method, you will still encounter the diamond problem, and will have to implement it separately in your Pegasus class (or get a compiler error).Ersatz
@Mikkel Løkke: The Pegasus class has to define overrides for the ambiguous methods but can implement them by just delegating to either super method (or both in a chosen order).Lethbridge
S
12

It is safe to keep a horse in a stable with a half door, as a horse cannot get over a half door. Therefore I setup a horse housing service that accepts any item of type horse and puts it in a stable with a half door.

So is a horse like animal that can fly even a horse?

I used to think a lot about multiple inheritance, however now that I have been programming for over 15 years, I no longer care about implementing multiple inheritance.

More often than not, when I have tried to cope with a design that pointed toward multiple inheritance, I have later come to release that I had miss understood the problem domain.

OR

If it looks like a duck and quacks like a duck but it needs batteries, you probably have the wrong abstraction.

Susquehanna answered 18/2, 2014 at 12:33 Comment(1)
If I read your analogy correctly, you're saying that in the beginning interfaces seem great, as they let you get around design problems, e.g. you can use someone else's API by forcing your classes through their interfaces. But after some years, you realized that the problem was bad design to begin with.Briefs
M
8

Java does not have a Multiple inheritance problem, since it does not have multiple inheritance. This is by design, in order to solve the real multiple inheritance problem (The diamond problem).

There are different strategies for mitigating the problem. The most immediately achievable one being the Composite object that Pavel suggests (essentially how C++ handles it). I don't know if multiple inheritence via C3 linearization (or similar) is on the cards for Java's future, but I doubt it.

If your question is academic, then the correct solution is that Bird and Horse are more concrete, and it is false to assume that a Pegasus is simply a Bird and a Horse combined. It would be more correct to say that a Pegasus has certain intrinsic properties in common with Birds and Horses (that is they have maybe common ancestors). This can be sufficiently modeled as Moritz' answer points out.

Monumental answered 17/2, 2014 at 9:35 Comment(0)
B
7

I think it depends very much on your needs, and how your animal classes are to be used in your code.

If you want to be able to make use of methods and features of your Horse and Bird implementations inside your Pegasus class, then you could implement Pegasus as a composition of a Bird and a Horse:

public class Animals {

    public interface Animal{
        public int getNumberOfLegs();
        public boolean canFly();
        public boolean canBeRidden();
    }

    public interface Bird extends Animal{
        public void doSomeBirdThing();
    }
    public interface Horse extends Animal{
        public void doSomeHorseThing();
    }
    public interface Pegasus extends Bird,Horse{

    }

    public abstract class AnimalImpl implements Animal{
        private final int numberOfLegs;

        public AnimalImpl(int numberOfLegs) {
            super();
            this.numberOfLegs = numberOfLegs;
        }

        @Override
        public int getNumberOfLegs() {
            return numberOfLegs;
        }
    }

    public class BirdImpl extends AnimalImpl implements Bird{

        public BirdImpl() {
            super(2);
        }

        @Override
        public boolean canFly() {
            return true;
        }

        @Override
        public boolean canBeRidden() {
            return false;
        }

        @Override
        public void doSomeBirdThing() {
            System.out.println("doing some bird thing...");
        }

    }

    public class HorseImpl extends AnimalImpl implements Horse{

        public HorseImpl() {
            super(4);
        }

        @Override
        public boolean canFly() {
            return false;
        }

        @Override
        public boolean canBeRidden() {
            return true;
        }

        @Override
        public void doSomeHorseThing() {
            System.out.println("doing some horse thing...");
        }

    }

    public class PegasusImpl implements Pegasus{

        private final Horse horse = new HorseImpl();
        private final Bird bird = new BirdImpl();


        @Override
        public void doSomeBirdThing() {
            bird.doSomeBirdThing();
        }

        @Override
        public int getNumberOfLegs() {
            return horse.getNumberOfLegs();
        }

        @Override
        public void doSomeHorseThing() {
            horse.doSomeHorseThing();
        }


        @Override
        public boolean canFly() {
            return true;
        }

        @Override
        public boolean canBeRidden() {
            return true;
        }
    }
}

Another possibility is to use an Entity-Component-System approach instead of inheritance for defining your animals. Of course this means, that you will not have individual Java classes of the animals, but instead they are only defined by their components.

Some pseudo code for an Entity-Component-System approach could look like this:

public void createHorse(Entity entity){
    entity.setComponent(NUMER_OF_LEGS, 4);
    entity.setComponent(CAN_FLY, false);
    entity.setComponent(CAN_BE_RIDDEN, true);
    entity.setComponent(SOME_HORSE_FUNCTIONALITY, new HorseFunction());
}

public void createBird(Entity entity){
    entity.setComponent(NUMER_OF_LEGS, 2);
    entity.setComponent(CAN_FLY, true);
    entity.setComponent(CAN_BE_RIDDEN, false);
    entity.setComponent(SOME_BIRD_FUNCTIONALITY, new BirdFunction());
}

public void createPegasus(Entity entity){
    createHorse(entity);
    createBird(entity);
    entity.setComponent(CAN_BE_RIDDEN, true);
}
Bibliofilm answered 17/2, 2014 at 9:22 Comment(0)
P
4

Ehm, your class can be the subclass for only 1 other, but still, you can have as many interfaces implemented, as you wish.

A Pegasus is in fact a horse (it is a special case of a horse), which is able to fly (which is the "skill" of this special horse). From the other hand, you can say, the Pegasus is a bird, which can walk, and is 4legged - it all depends, how it is easier for you to write the code.

Like in your case you can say:

abstract class Animal {
   private Integer hp = 0; 
   public void eat() { 
      hp++; 
   }
}
interface AirCompatible { 
   public void fly(); 
}
class Bird extends Animal implements AirCompatible { 
   @Override
   public void fly() {  
       //Do something useful
   }
} 
class Horse extends Animal {
   @Override
   public void eat() { 
      hp+=2; 
   }

}
class Pegasus extends Horse implements AirCompatible {
   //now every time when your Pegasus eats, will receive +2 hp  
   @Override
   public void fly() {  
       //Do something useful
   }
}
Pheni answered 17/2, 2014 at 8:59 Comment(0)
P
4

you can have an interface hierarchy and then extend your classes from selected interfaces :

public interface IAnimal {
}

public interface IBird implements IAnimal {
}

public  interface IHorse implements IAnimal {
}

public interface IPegasus implements IBird,IHorse{
}

and then define your classes as needed, by extending a specific interface :

public class Bird implements IBird {
}

public class Horse implements IHorse{
}

public class Pegasus implements IPegasus {
}
Paleopsychology answered 17/2, 2014 at 9:0 Comment(6)
Or he can just: Public class Pegasus extends Animal Implements Horse , BirdPeterman
OP is already aware of this solution he is looking for alternate way to do itFaker
@Batman, of course he canm but if he wants to extend the hierarchy he would need to follow this approachPaleopsychology
IBird and IHorse should implement IAnimal instead of AnimalTouber
@Yogesh, you are right. I overlooked the place where he states it. As a "newbie" what should I do now, delete the answer, or leave it there?, thanks.Paleopsychology
I don't know take loot at this meta.stackexchange.com/questions/37738/…Faker
O
3

Interfaces don't simulate multiple inheritance. Java creators considered multiple inheritance wrong, so there is no such thing in Java.

If you want to combine the functionality of two classes into one - use object composition. I.e.

public class Main {
    private Component1 component1 = new Component1();    
    private Component2 component2 = new Component2();
}

And if you want to expose certain methods, define them and let them delegate the call to the corresponding controller.

Here interfaces may come handy - if Component1 implements interface Interface1 and Component2 implements Interface2, you can define

class Main implements Interface1, Interface2

So that you can use objects interchangeably where the context allows it.

So in my point of view, you can't get into diamond problem.

Okubo answered 17/2, 2014 at 8:59 Comment(1)
Its not wrong in the same way that direct memory pointers, unsigned types and operator overloading are not wrong; it's just not necessary to get the job done. Java was designed as a lean language easy to pickup. Don't make stuff up and hope for the best, this is a field of knowledge, not guesses.Hypnotic
A
3

As you will already be aware, multiple inheritance of classes in Java is not possible, but it's possible with interfaces. You may also want to consider using the composition design pattern.

I wrote a very comprehensive article on composition a few years ago...

https://codereview.stackexchange.com/questions/14542/multiple-inheritance-and-composition-with-java-and-c-updated

Aedile answered 17/2, 2014 at 13:4 Comment(0)
C
3
  1. Define interfaces for defining the capabilities. You can define multiple interfaces for multiple capabilities. These capabilities can be implemented by specific Animal or Bird.
  2. Use inheritance to establish relationships among classes by sharing non-static and non-public data/methods.
  3. Use Decorator_pattern to add capabilities dynamically. This will allow you to reduce number of inheritance classes & combinations.

Have a look at below example for better understanding

When to Use the Decorator Pattern?

Cary answered 15/12, 2016 at 9:11 Comment(0)
B
2

To solve the problem of mutiple inheritance in Java → interface is used

J2EE (core JAVA) Notes By Mr. K.V.R Page 51

Day - 27

  1. Interfaces are basically used to develop user defined data types.
  2. With respect to interfaces we can achieve the concept of multiple inheritances.
  3. With interfaces we can achieve the concept of polymorphism, dynamic binding and hence we can improve the performance of a JAVA program in turns of memory space and execution time.

An interface is a construct which contains the collection of purely undefined methods or an interface is a collection of purely abstract methods.

[...]

Day - 28:

Syntax-1 for reusing the features of interface(s) to class:

[abstract] class <clsname> implements <intf 1>,<intf 2>.........<intf n>
{
    variable declaration;
    method definition or declaration;
};

In the above syntax clsname represents name of the class which is inheriting the features from ‘n’ number of interfaces. ‘Implements’ is a keyword which is used to inherit the features of interface(s) to a derived class.

[...]

Syntax-2 inheriting ‘n’ number of interfaces to another interface:

interface <intf 0 name> extends <intf 1>,<intf 2>.........<intf n>
{     
    variable declaration cum initialization;
    method declaration;
};

[...]

Syntax-3:

[abstract] class <derived class name> extends <base class name> implements <intf 1>,<intf 2>.........<intf n>
{
  variable declaration;
  method definition or declaration;
};
Brookner answered 19/2, 2014 at 17:49 Comment(0)
L
2

To reduce the complexity and simplify the language, multiple inheritance is not supported in java.

Consider a scenario where A, B and C are three classes. The C class inherits A and B classes. If A and B classes have same method and you call it from child class object, there will be ambiguity to call method of A or B class.

Since compile time errors are better than runtime errors, java renders compile time error if you inherit 2 classes. So whether you have same method or different, there will be compile time error now.

class A {  
    void msg() {
        System.out.println("From A");
    }  
}

class B {  
    void msg() {
        System.out.println("From B");
    }  
}

class C extends A,B { // suppose if this was possible
    public static void main(String[] args) {  
        C obj = new C();  
        obj.msg(); // which msg() method would be invoked?  
    }
} 
Linguiform answered 24/2, 2015 at 14:33 Comment(0)
O
-1

Problem not solved. To sufficiently model this out and to prevent code replication you'd either need multiple inheritance or mixins. Interfaces with default functions are not sufficient because you cannot hold members in interfaces. Interface modeling leads to code replication in subclasses or statics, which is both evil.

All you can do is to use a custom construction and split it up in more components and compose it all together...

toy language

Oz answered 21/9, 2020 at 9:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.