1

I am currently perusing through Jdk 8 and I came across the feature where you have multiple interfaces that overlap with the same method signature for a default method, the compiler will throw an error if you try to have one class implement both interfaces, to prevent the problem of ambigious methods with multiple inheritance.

My question is, why can't java also allow multiple inheritance with classes like it does with interfaces, and solve the ambigious field and method problem that results from multiple inheritances by simply throwing an exception like it does when implementing multiple interfaces that have identical default method signatures?

SteelToe
  • 1,539
  • 3
  • 13
  • 22
  • 2
    Ever heard of diamond hierarchy problem? – Raja Anbazhagan Jan 10 '17 at 06:21
  • 4
    I really don't like the term "inheritance of interfaces". I'd rather use "implementation of multiple interfaces". Inheritance implies that you're receiving something ready and for free, while implementation defines you have an obligation. They're totally opposites in this context in my opinion. – Machado Jan 10 '17 at 12:55
  • Much as I wanted to make this an answer, my memory had too many holes, but: another reason Java doesn't do MI is due to the way method pointers are stored. They're offsets from the beginning of a class definition in a classfile. This has critical implications for how the bytecode instructions `invokestatic`, `invokespecial`, and `invokevirtual` work. IIRC, `invokevirtual` works faster than it would otherwise, because it can rely on certain methods being at certain offsets. Interface methods don't threaten this. Multiple classes, however, would. – Paul Brinkley Jan 10 '17 at 17:44

4 Answers4

6

Partially, this is historical. It would be much more difficult to add multiple inheritance now. For example, the Class.getSuperclass() method would no longer make sense, as a class might have multiple superclasses. Any code that depends on the single-inheritance nature of Java would break.

Fields are more problematic for multiple inheritance than methods. Consider the case that you want to inherit from two superclasses each of which have a foobar field. What happens? You propose that the compiler simply reject this. But this would mean that there were certain pairs of classes that couldn't be inherited together just because they happened to use the same field name. This is different from methods, because for methods you can simply override the method with the desired behavior.

Of course, you could come up with some semantics for multiple inheritance to make fields work properly. However, it would end up introducing a fair amount of additional complexity. In the eyes of java designers, multiple inheritence simply is not useful enough to warrant the additional complexity.

Winston Ewert
  • 24,732
  • 12
  • 72
  • 103
4

You are asking the wrong question. It's not "why can't Java", it's "why doesn't Java". Answer: Multiple inheritance is a pain in the arse. Most C++ code doesn't use multiple inheritance. Two highly popular languages, Objective-C and Swift, don't have multiple inheritance and nobody is complaining (and one of them is brand new, so multiple inheritance isn't missing for historical reasons, but because someone said "it's not worth the bother"). And in C++, most actual uses come from someone confusing "is a" and "has a" and would be handled better in a different way.

For example, I implement a button that displays some text in some color. Multiple inheritance would inherit from button, string, and color. The correct way is to inherit from button, and have two instance variables of type string and color.

Interfaces are an entirely different matter. Interfaces are often used for delegates, and it is entirely normal for an instance to be a delegate for multiple classes, and therefore to support multiple interfaces. Supporting an interface doesn't inherit anything, it adds a requirement for the developer to support certain methods. Multiple interfaces just add multiple requirements for the developer.

gnasher729
  • 42,090
  • 4
  • 59
  • 119
4

As mentioned in other answers, the main reason is the diamond inheritance problem. Prior to Java 8, there were no default interfaces so this issue did not exist in Java at all and this was completely intentional.

A different but related question would be: "if the diamond inheritance problem is so bad, why was it introduced in Java 8?" To understand that you need to understand why the default keyword was introduced to allow method implementations on interfaces. The reason is that once an interface was released, it was impossible to add anything to it without breaking existing dependencies on that interface. By adding a default implementation, interfaces are more free to evolve.

So let's go back to your question. What's good for the goose is good for the gander, right? Well, interfaces are more like ducks. The point of a default method is not meant to be a place to add non-trivial implementations. I think a good example of it's use is the remove() method on Iterator. In the past whenever you wanted to implement an iterator, you had to specify a remove() method which (in my experience) is almost always to throw an unsupported operation exception. The addition of default is not meant to change the point of interfaces. It's a pragmatic addition, not a conceptual one.

The thing to keep in mind with default implementations is that in the spec for polymorphic method binding for Java, any class in the inheritance hierarchy takes precedence over any default method even if that class doesn't implement the interface that defined it. If you add multiple inheritance of classes, this simple rule which is the most straightforward way to resolve conflicts becomes vastly more complicated. There is no corresponding rule that can be applied for classes.

JimmyJames
  • 24,682
  • 2
  • 50
  • 92
0

Why multiple inheritance is not more popular? Take the example:

  class X 
  {
      public void doSomething() { ... }
  }
  class Y
  {
      public void doSomething() { ... }
  }
  class Z extends X, Y
  {
  }

What should method doSomething of class Z do? In multiple inheritance many such conflicts do exist. On single inheritance you would be forced to use delegation. Which is annoying but more controlled.

In that examples you can define it is the doSomething of the first extended class. However if you imagine X has no doSomething, you develop your extension believing the Y.doSomethibg will be called and the author of X class latter added the doSomething, then a modification on the base library will introduce a inconsistency on your code that the compiler will not recognize.

I am not defending the status quo. I think languages need to evolve and incorporate patterns and other kinds of polimorphimsm... For example, most of time the builder pattern is a ugly hack for the lack of named parameters. I I use it on Java, but not in JavaScript. But modify that takes time and a lot of research.

Lucas
  • 298
  • 1
  • 4