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 } }
Interfaces provide an alternative to multiple inheritance. Java programming language does not support multiple inheritance. But interfaces provide a good solution. Any class can implement a particular interface and importantly the interfaces are not a part of class hierarchy.
You could use pattern strategy to define different behaviors and make the subclasses implement them.
Delegation can be an alternative to inheritance. Delegation means that you use an object of another class as an instance variable, and forward messages to the instance.
However, a class can implement one or more interfaces, which has helped Java get rid of the impossibility of multiple inheritances. The reason behind this is to prevent ambiguity. Consider a case where class B extends class A and Class C and both class A and C have the same method display().
You could use pattern strategy to define different behaviors and make the subclasses implement them.
Like in this picture :
It's French (dictionary below) but pretty self-explanatory :
Personnage
are characters used in a video game.EspritCombatif
, Deplacement
, Soin
) define the method in the interface. They are the behaviors.Personnage
class contains an object of each of the interfaces defined on the right.Personnage
) chooses what code to implement by doing for example a combat = new CombatCouteau();
in the constructor.So if you want to change only the behavior of all the guys that fight with a knife, you just change the code in CombatCouteau
.
Dictionary :
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With