2

I have a class hierarchy like that:

abstract class BaseThing
{
    public abstract void doSomething();
}

class Thing1 extends BaseThing
{
    @Override
    public void doSomething()
    {
        doSomethingWithThing1();
    }
}

class Thing2 extends BaseThing
{
    @Override
    public void doSomething()
    {
        doSomethingWithThing2();
    }
}

// A dozen more classes that extend the BaseThing class. 

I need to create an extended version of the whole tree. There is no multiple inheritance in Java, so I created it as:

interface BaseThingExt
{
   public void doSomethingElse();
}

class Thing1Ext extends Thing1 implements BaseThingExt
{
    @Override
    public void doSomethingElse()
    {
        doSomethingElseWithThing1();
    }
}

//   All Thing.. classes are extended by ThingExt... classes

Now the question. Where can I put some common fields for all ThingExt classes? I cannot place them in the base interface, as they would become final static. I cannot make BaseThingExt an abstract class as Java doesn't support a multiple inheritance. I cannot believe the only solution is to replicate them a dozen times in all ThingExt classes!

EDIT: Please note that all ThingExt classes should extend their according Thing classes and not just the BaseThing class, because there are some specifics in each derived class. So the answer by @Hamdi Douss won't work.

8
  • Why don't you implement BaseThingExt in BaseThing and extend Thing1 and Think2 continuously . Commented May 1, 2016 at 9:42
  • @Shree Krishna: BaseThing and BaseThingExt are living in the different packages. There are situations when only BaseThing should be available to clients. Commented May 1, 2016 at 9:45
  • Can you not create an abstract class that implements the interface, including your fields, with abstract getters/setters methods to implement and extend concrete classes? Commented May 1, 2016 at 9:45
  • Your design is what is forcing the reproduction a dozen times. You're wasting the one extension you have on what could be covered by an interface. Commented May 1, 2016 at 9:47
  • @Mark Keen: I can, but as BaseThingExt already extends BaseThing, it cannot extends this abstract class also. Commented May 1, 2016 at 9:48

2 Answers 2

7

The usual trick is to use composition rather than inheritance:

interface BaseThingExt
{
   public void doSomethingElse();
}

class ConcreteImplementation implements BaseThing, BaseThingExt {

    private final BaseThing thingDelegate;
    private final BaseThingExt extDelegate;

    public ConcreteImplementation(BaseThing thing, BaseThingExt ext) {
        this.thingDelegate = thing;
        this.extDelegate = ext;
    }


    @Override
    public void doSomething() {
        thingDelegate.doSomething();
    }

    @Override
    public void doSomethingElse() {
        extDelegate.doSomethingElse();
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

I finally understood what is badgering me about this solution. I would have to have 2 instances, one of Thing class and one of ThingExt class for each ConcreteImplementation object, instead of having just one now. Am I right or am I missing something?
Yes. The idea is that you have a class hierarchy of Thing, and class hierarchy of ThingExt, and this class allows creating an instance of both, using any member of both hierarchies.
3

I suggest to add a super class AbstractBaseThingExt:

abstract class AbstractBaseThingExt implements BaseThingExt
{
    private Object commonField;
    public Object getCommonField(){}
    public Object setCommonField(Object commonField){}
}

class ThingExt extends AbstractBaseThingExt
{
    public ThingExt(BaseThing base) {
        this.base = base;
    }

    public void doSomething()
    {
        this.base.doSomething();
    }
}

The class ThingExt should delegate implementation to base when appropriate.

4 Comments

won't work. Thing1Ext should extend Thing1 and not the BaseThing, there are some common specifics here.
Got it. In that case, the only solution you have is to use composition: class ThingExt extends AbstractBaseThingExt with AbstractBaseThingExt being your abstract class that holds common fields. Then ThingExt should take a BaseThing in the constructor. Editing my answer...
@Flot2011, your own proposed solution does just that tho. ThingXExt extends ThingX which extends BaseThing. You can't remove the inheritance of BaseThing further down the hierarchy.
@ChiefTwoPencils: Yes, but I can use a code specific to Thing1 in Thing1Ext without typecasting it all around.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.