• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
  • Tim Cooke
  • Campbell Ritchie
  • Ron McLeod
  • Junilu Lacar
  • Liutauras Vilda
  • Paul Clapham
  • Jeanne Boyarsky
  • Henry Wong
Saloon Keepers:
  • Tim Moores
  • Tim Holloway
  • Stephan van Hulst
  • Piet Souris
  • Carey Brown
  • Jesse Duncan
  • Frits Walraven
  • Mikalai Zaikin

How is Java's interfaces an improvement over C++'s multiple inheritance ?

Posts: 13
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I have a doubt (a pretty common one I should say). No doubt it might have been discussed elsewhere, but I would appreciate any feedback to help clear my doubts. Let me elaborate a bit ..
I read in many places that one of Java's positive points is that, it got rid of 'confusing and sparingly used multiple inheritance' feature of C++ and Java provides similar facility with a 'better' solution - 'interfaces' which can be used to mimic MI.
One of the classic problems with MI is the 'Diamond problem':
1. Child classes C2 and C3 inherit from parent class - C1
2. Grandchild C4 inherits from C2 and C3
Now the problems here are:
1. How many copies of C1 should be there in an instance of
C4 ?
2. If C2 and C3 both have a method M1()with exactly same signature, how will the conflict be resolved ?
3. Should C4.M1() message be be sent to C2.M1() or C3.M1()implementation?(assuming that C4 does not override M1() )
Problem 1 could be resolved in C++ by declaring C1 as 'virtual'.
Could someone shed somelight on how the other 2 problems are overcome in C++ ?
Also what is Java's solution for situation 2 occuring with its
interfaces? Say interfaces I1 and I2 both have a method with exactly same signature - M1(). If Class C1 wants to implement both I1 and I2 how is the conflict resolved ? At compile time or runtime ?
Remember, the main question is still in the subject line !!
Thanks for all your inputs.
Ranch Hand
Posts: 18944
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
From the easiest to the hardest ...
Regarding Java's solution for situation 2 with interfaces: Let's deal with this in two parts, first the inheritance of the (abstract) methods in I1 and I2, then their implementation in C4.
In Java, a class may inherit multiple methods with the same signature. In your scenario they are both declared in interfaces, so they are both abstract. Both of the methods must have the same return type. Their declared exceptions may be the same or may differ; the compiler doesn't care. (By the way, all of the inheritance part is handled by the compiler.) You can leave this situation as it stands now by not implementing the methods, and C4 will be abstract.
When you implement the methods, either in C4 or in a class derived from it, things get more restrictive. You only get to provide one implementation for a given descriptor (signature + return type) in a single class, and it will override both of the abstract methods. The concrete method's declared exceptions must not conflict with either of the interface method declarations. Again, this part is handled at compile time.
For the full story, see JLS 2e
You didn't specifically ask about invocation, but I'll just note that finding the method body to execute is simple in this case but complex in general. If you invoke M1 through a reference to an instance of C4 or a subclass, the (possibly inherited) declaration in that class will be found by the compiler and remembered for use at runtime. If you invoke M1 through a reference to I1 or I2, that declaration will be used instead. Later, at run time, the VM will begin the search for a corresponding declaration with a concrete method body in the actual class of the object referred to in your invocation (despite the type of reference you use). This search will continue up the inheritance chain until a method body is found. In this case, the body will be found in C4.
There are more opportunities for complexity if C4 extends C3 and implements I1, and both C3 and I1 declare an M1. I'm sure you're glad of that; we need more complexity.
Enough of that.
Regarding C++'s handling of situations 2 and 3, I'm assuming that C2 and C3 each introduce a method M1 that was not previously declared in C1. (If M1 was introduced in C1 then virtual inheritance handles the situation, as you've noted.) C4 effectively has a method C2::M1 and another method C3::M1, and that's how it has to refer to them. Pretty straightforward, actually, which brings us to the issue you originally raised.
Don't believe the hype. <i>Java is not simpler than C++.</i> Java does omit some features of C++, like pointer arithmetic, explicit memory management, and operator overloading (I miss it, sniff), but you can't reduce the complexity of something by removing parts of it. What's left is just as complex as it was before. The big virtue of Java over C++ is increased separation of compile-time code and run-time execution. This separation is the foundation of Java's safety and platform independence, and its specific applicability to network programming. It seems to me that the design decisions to not allow pointer arithmetic and to provide automatic memory management were made mainly to increase run time safety, which is critical if networked code is to be trusted. The multiple inheritance differences between the languages (yes, Java has multiple inheritance, you just have to use pure abstract classes - interfaces, that is) favor C++, in my humble opinion. The C++ model is arguably simpler, and certainly more powerful.
Java targets a specific programming realm (networked systems), and does it very well. C++ is designed for a much broader range of applications.
I think the reason for the common misperception of Java's simplicity is the rich run time library supplied by Sun. (Note that this too is made practical by the separation of compile-time processing and run-time environment.) Novice programmers can stitch together pre-built components to form working non-trivial programs with good user interfaces. This is a very good thing, but the complexity is just hidden in the library - its still there.
Thank you for your thought-provoking questions. I hope this little diatribe is of some use (or at least entertainment) to you.
Mahesh Hegde
Posts: 13
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks a lot jply. I had read some very good articles on Inheritance, Interfaces, Composition etc. by Bill Venners at www.artima.com. But still had those doubts which are now cleared by your excellent reply.
To summarize my understanding, with multiple inheritance of Java interfaces(in the scenario considered), implementations are not inherited and the child classes' implementation will override both I1.M1() and I2.M1(). C4.M1() will be the only one available, thus avoiding the conflict at compile time.
Even with more complex situations, at run time also there will not be any conflict because the method invoked will depend on - class of the actual object(C4) reference and not the type of the variable holding it (c1, C2, C3 or C4).
Thanks again
pie. tiny ad:
Building a Better World in your Backyard by Paul Wheaton and Shawn Klassen-Koop
    Bookmark Topic Watch Topic
  • New Topic