Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can interfaces replace the need for multiple inheritance when have existing classes

People also ask

How does interface helps in multiple inheritance?

An interface contains variables and methods like a class but the methods in an interface are abstract by default unlike a class. Multiple inheritance by interface occurs if a class implements multiple interfaces or also if an interface itself extends multiple interfaces.

What is the replacement of multiple inheritance?

Interfaces provide an alternative to multiple inheritance. Java programming language does not support multiple inheritance. But interfaces provide a good solution. Any class can implement a particular interface and importantly the interfaces are not a part of class hierarchy.

Can we achieve multiple inheritance by using interface?

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.

Why does java allow multiple inheritance for interfaces but not for classes?

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.


Actually, I have no good answer other than Java SHOULD have Multiple Inheritance. The whole point that interfaces should be able to replace the need for Multiple Inheritance is like the big lie that when repeated enough times becomes true.

The argument is that Multiple Inheritance causes all these problems (la-di-dah), yet I keep hearing those arguments from Java developers who have never used C++. I also don't EVER remember C++ programmers saying "Gee, I love C++, but if they would only get rid of Multiple Inheritance, it would become a great language". People used it when it was practical and didn't when it wasn't.

Your problem is a classic case of where Multiple Inheritance would be appropriate. Any suggestion to refactor the code is really telling you how to work around the PROBLEM that Java has no Multiple Inheritance.

Also all the discussion that "oh, delegation is better, la-di-dah" is confusing religion with design. There is no right way. Things are either more useful or less useful and that is all.

In your case Multiple Inheritance would be more useful and a more elegant solution.

As far as refactoring your code into a less useful form to satisfy all the religious people who have never used Multiple Inheritance and believe "Multiple Inheritance is bad", I guess you will have to downgrade your code because I don't see Java "improving" in that way any time soon. There are too many people repeating the religious mantra to the point of stupidity that I can't see it ever being added to the language.

Actually, my solution for you would be "x extends Tagged, XMLElement" and that would be all.

...but as you can see from the solutions provided above, most people think that such a solution would be WAY TOO COMPLEX AND CONFUSING!

I would prefer to venture into the "x extends a,b" territory myself, even if it is a very frightening solution that might overwhelm the abilities of most Java programmers.

What is even more amazing about the solutions suggested above is that everyone here who suggested that you refactor your code into "delegation" because Multiple Inheritance is bad, would, if they were confronted with the very same problem, would solve the problem by simply doing: "x extends a,b" and be done with it, and all their religious arguments about "delegation vs inheritance" would disappear. The whole debate is stupid, and it only being advanced by clueless programmers who only demonstrate how well they can recite out of a book and how little they can think for themselves.

You are 100% correct that Multiple Inheritance would help, and no, you are doing anything wrong in your code if you think Java should have it.


You should probably favor composition (and delegation) over inheritance :

public interface TaggedInterface {
    void foo();
}

public interface XMLElementInterface {
    void bar();
}

public class Tagged implements TaggedInterface {
    // ...
}

public class XMLElement implements XMLElementInterface {
    // ...
}

public class TaggedXmlElement implements TaggedInterface, XMLElementInterface {
    private TaggedInterface tagged;
    private XMLElementInterface xmlElement;

    public TaggedXmlElement(TaggedInterface tagged, XMLElementInterface xmlElement) {
        this.tagged = tagged;
        this.xmlElement = xmlElement;
    }

    public void foo() {
        this.tagged.foo();
    }

    public void bar() {
        this.xmlElement.bar();
    }

    public static void main(String[] args) {
        TaggedXmlElement t = new TaggedXmlElement(new Tagged(), new XMLElement());
        t.foo();
        t.bar();
    }
}

Similar to what Andreas_D suggested but with the use of inner classes. This way you indeed extend each class and can override it in your own code if desired.

interface IBird {
    public void layEgg();
}

interface IMammal {
    public void giveMilk();
}

class Bird implements IBird {
    public void layEgg() {
        System.out.println("Laying eggs...");
    }
}

class Mammal implements IMammal {
    public void giveMilk() {
        System.out.println("Giving milk...");
    }
}

class Platypus implements IMammal, IBird {

    private class LayingEggAnimal extends Bird {}
    private class GivingMilkAnimal extends Mammal {}

    private LayingEggAnimal layingEggAnimal = new LayingEggAnimal();

    private GivingMilkAnimal givingMilkAnimal = new GivingMilkAnimal();

    @Override
    public void layEgg() {
        layingEggAnimal.layEgg();
    }

    @Override
    public void giveMilk() {
        givingMilkAnimal.giveMilk();
    }
}

First it makes no sense to put the real implementation in all data classes since it is the same every time but this would be necessary with interfaces (I think).

How about using aggregation for the tags?

  1. Rename your Tagged class to Tags.

  2. Create a Tagged interface:

    interface Tagged { Tags getTags(); }

  3. Let each class that needs to be "tagged", implement Tagged and let it have a tags field, which is returned from getTags.

Second I don't see how I could change one of my inheritance classes to an interface. I have variables in here and they have to be exactly there.

That's right, interfaces can't have instance variables. The data structures storing the tags however, shouldn't necessarily IMO be part of the classes that are tagged. Factor out the tags in a separate data structure.


I'd solve it that way: extract interfaces for the Tagged and XMLElement class (maybe you don't need all methods in the public interface). Then, implement both interfaces and the implementing class has a Tagged (your actual concrete Tagged class) and an XMLElement (your actual concrete XMLElement class):

 public class MyClass implements Tagged, XMLElement {

    private Tagged tagged;
    private XMLElement xmlElement;

    public MyClass(/*...*/) {
      tagged = new TaggedImpl();
      xmlElement = new XMLElementImpl();
    }

    @Override
    public void someTaggedMethod() {
      tagged.someTaggedMethod();
    }
  }

  public class TaggedImpl implements Tagged {
    @Override
    public void someTaggedMethod() {
      // so what has to be done
    }
  }

  public interface Tagged {
     public void someTaggedMethod();
  }

(and the same for XMLElement)


one possible way;

1- You can create base class(es) for common functionality, make it abstract if you dont need to instantiate it.

2- Create interfaces and implement those interfaces in those base class(es). If specific implementation is needed, make the method abstract. each concrete class can have its own impl.

3- extend the abstract base class for in concrete class(es) and implement specific interfaces at this level as well