views:

248

answers:

6

I'm working with a certain API library in Java. It has a base class A, as well as B and C which both extend A. B & C provide similar but distinct functionality, all three classes are in the library.

public abstract class A
{
    virtual foo();
}

public class B extends A {}
public class C extends A {}

How do I get elements of A, B, and C in my class? If I use interfaces to implement the classes, there is a lot of duplicate code, and inner classes will not allow me to override existing methods so that the calling interfaces of A, B, and C are preserved.

How do I implement multiple inheritence in Java?

EDIT: Thanks for edit George, its more clear now, forgot to mention one critical requirement: my classes must have A as a base so that they can be managed by platform API.

A: 

Sounds like you want to extend A - call it D - override its foo(), and then have new subclasses E & F that extend D and add their own functionality.

You might think about extracting common interfaces and reusing those. A good IDE with refactoring capability will make it easy to do.

duffymo
+8  A: 

To recap, you have:

class A
{
    public void foo() {}
}

class B extends A
{
    public specificAMethod() {}
}

class C extends A
{
    public specificCMethod() {}
}

The above classes are in a library that you can't access or modify. You want to get the behaviour of both B and C in a third class D, as if it were possible to write:

class D extends B, C
{
}

Right?

What about using B and C instead of inheriting? Do you really need inheritance? You want to call private B and C methods?

class D
{

private B b;
private C c;
}
vulkanino
prefer composition over inheritance!
Bill K
@Bill did you read "head first design patterns"? :) I did.
vulkanino
This is same as delegation
Saideira
I was agreeing with you--voted you up @vulkanio--because that's pretty much what you were saying (I just summarized). Hope it didn't come across as telling you you were doing it wrong or something.
Bill K
This is delegation once again. The reason I want my classes to have ultimately A as a base is so that I can pass it into the platform API, as these are all platform managed objects.
Saideira
@Saideira Generally things you have to pass in to an API are specified as interfaces, if not someone didn't really understand how to write an API, but if you can't use an interface then extend the class that you need to use and compose the second class into your object.
Bill K
@Bill I was just asking because in that book that sentence is repeated over and over, I'm not complaining about your comment, which I second :)
vulkanino
D could extend A and still contain a B and a C as members, which themselves each extend A
crowne
@vulkanino I read the first Design Patterns book quite a while ago, not Head First, but my feelings about inheritance really come from experience. In my earlier designs, touching a single class always spread up and down the tree and would require way too many changes. Once I learned to isolate my classes a bit and get really comfortable with encapsulation, things got much happier. Same with many language other features besides inheritance, you discover them, then hate them, come to understand them, abuse them, and finally learn to use them appropriately (Pity this stage isn't always reached).
Bill K
A: 

Multiple class inheritance is not possible in Java, however you can use multiple inheritance for interfaces. Using Delegation pattern you can combine behavior of several other classes into one.

Eugene Kuleshov
Yes, i can use delegation but have to write A LOT of glue code as the classes have many methods
Saideira
For the most part IDE could generate it for you or you could use dynamic proxy. See, for example http://java.sys-con.com/node/37748
Eugene Kuleshov
@Saideria any chance your classes are too big? If your interface is forwarding that much stuff, I wonder if you could be doing something wrong. For instance, you might have setters and getters--in general try to eliminate those and put the code that called them in your class. Could your class be doing more than one simple thing? Perhaps it should be broken up into multiple classes... This is something that has no right answer, but try to do this kind of stuff repeatedly, every time you look at any code. In the long run it's totally worth the time.
Bill K
+2  A: 

If you take the general approach of "Prefer Composition over Inheritance", you may find out that one or both of the classes shouldn't be actually "Inherited" anyway. In both cases, do the classes have a strict "is-a" relationship? If you can say "Has-a" out loud and it doesn't sound stupid, you probably want composition.

For instance, if you are implementing a deck of cards, the 3 of spades is-a 3 and it is-a spade, but you can also think of it as it has-a 3 and it has-a suit (spade). Since you can think of it that way, you should probably prefer the has-a interpretation and use composition.

Try to stay away from inheritance trees more than a few objects deep--and if you ever feel the desire to use multiple inheritance, try to work around it. This is one of the cases where Java kind of forces you to design your code to be a little more readable by not supplying a feature (but admittedly when you really want it, it's not there and that can hurt! Some level of mixin would be nice).

Bill K
A: 

Groovy, while technically another language, can be used as an extension to Java, since most Java code also works in Groovy. Groovy has the ability for you to inject/intercept methods in existing Java classes. Just thought I'd throw it out there, in case you hadn't thought of it.

Marcus Adams
A: 

Completely different approach is applied in COM: all objects inherit from IUnknown, which has a method that could be translated to Java as:

Object queryInterface(Class<?> clazz)

The simplest implementation of this method can be:

if(clazz.isAssignableFrom(this.getClass()))
    return this;
else
    return null;

Where single inheritance won't work, it's just enough to add:

else if(class == SomeClass.class) {
    return something;
} else ...

This way even most complex multiple inheritance cases can be tackled and you get full control over what is returned and when, so you avoid many problems with 'classical' multiple inheritance from languages like C++, like fork-join problem.

iirekm