jeudi 26 mars 2015

Alternative for multiple inheritance

After 20 or so years programming Java for the first time I wish I had multiple inheritance. But I don't so I'm looking for an alternative for this concrete problem.


The real application is some kind of ERP and somewhat complex so I try to translate this problem to cars. This only goes so far but it's the best I can do.


Lets start with an interface describing what a car can do:



public interface Car {

public String accelerate();
public String decelerate();

public String steerLeft();
public String steerRight();
}


Now we have a basic (but not abstract) implementation:



public class BasicCar implements Car {

protected final String name;

public BasicCar( String name ) {

this.name = name;
}

// In the real word this method is important and does lots of stuff like calculations and caching
protected String doDrive( String how ) {
return name + " is " + how + "ing";
}
@Override
public String accelerate() {
return doDrive( "accelerat" );
}
@Override
public String decelerate() {
return doDrive( "decelerat" );
}


// This method is important, too
protected String doSteer( String where ) {
return name + " is steering to the " + where;
}
@Override
public String steerLeft() {
return doSteer( "left" );
}
@Override
public String steerRight() {
return doSteer( "right" );
}
}


In the real world this itself is a facade to a DAO. Note that I need the methods @doDrive@ and @doSteer@ to be there because this is where the real work like some calculations, translations and caching is done.


And some more concrete implementations:



public class Sportscar extends BasicCar {

public Sportscar( String name ) {
super( name );
}

// I need to call the super method
@Override
public String doDrive( String how ) {
return super.doDrive( how ) + " fastly";
}
}

public class Truck extends BasicCar {

public Truck( String name ) {
super( name, new BasicMotor(), new TruckySteerer() );
}

// I need to call the super method
@Override
public String doSteer( String where ) {
return super.doSteer( where ) + " carefully";
}
}


What I can do right now is:



Car mcqueen = new Sportscar( "McQueen" );
mcqueen.steerLeft() //-> "McQueen is steering left"
mcqueen.accelerate() // -> "McQueen is accelerating fastly"

Car mack = new Truck( "Mack" );
mack.steerLeft() //-> "McQueen is steering left carefully"
mack.accelerate() // -> "McQueen is accelerating"


What I now want to do is combining these two into one which shares their functionallity:



Car red = new Firetruck( "Red" );
red.steerLeft() //-> "Red is steering left *carefully*"
red.accelerate() // -> "Red is accelerating *fastly*"


What I tried / thought about


I could copy&paste code from both into one class. But this is never a good idea. And in the real application this is pretty much code so it's an even worse idea.


I think I'm facing some major rewrite/refactoring here.


So I could make @Sportscar@ and @Truck@ a Decorator and for @Firetruck@ use both. But this won't work because @doSteer@ and @doDrive@ are called from within the decorated objects whereas a decorator only works for calles from the "outside". So I would have to put these methods in the decorator, too and this isn't a good idea either.


So I could use Java8's new fancy features and make @doSteer@ and @doDrive@ delegating to an interface like:



@FunctionalInterface
interface Driver {
public String doDrive( String where );
}


And feeding it to the constructor of @BasicCar@ but then (apart from getting pretty complex and getting some other rather nasty java problems with @final@) I don't have access to the state of @BasicCar@ in a good way anymore.


So currently I'm a little lost here. Any good ideas would be appretiated.


Aucun commentaire:

Enregistrer un commentaire