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() //-> "Mack is steering left carefully"
mack.accelerate() // -> "Mack 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.
EDIT: To give an example how this looks in the real world: The doSteer
group could be something like:
class ProductImpl {
String getTitle(){
return getField( "title" );
}
String getTeaser(){
return getField( "teaser" );
}
String getField( String name ){
Locale loc = configuredLocale();
Map vars = configuredVarialbes();
String value = getCached( name, loc );
value = translateVariables( value );
value = replaceVariables( value, vars );
// and more
}
}