Prefer composition/delegation over inheritance

Inheritance not very robust

There are numerous hints that inheritance is not very stable under refactoring; see, for example, Bloch, "Effective Java".

Use delegation in eclipse

We therefore suggest to prefer composition (=delegation) over inheritance where this is possible.  It is only possible when the class that one wants to inherit from implements an interface.  In that case, the following is possible (with eclipse):

1. Write a class skeleton as follows:

class MyClass implements XXXInterface {
   private XXXInterface delegate = new XXXImplementation(...) ;
}

2. In eclipse, go to "source"/"generate delegate methods" and follow the instructions.

[[Somebody please add a screenshot here. thanks. kai]]

This will delegate all method calls to MyClass to the delegate.  Now you can modify some of the delegate methods as you like.

(This sometimes seems to provide less access than inheritance, but I don't think this is true as long as you assume that internal variables/fields are always private.)

The typical example

It is called "composition" since you can do this with more than one interface/delegate.  The classical example is something like

class MyCar implements HasSteering, HasBrakes, HasGears {
   private HasSteering steeringDelegate = new PowerSteering(...) ;
   private HasBrakes   brakesDelegate   = new SimpleBrakes(...) ;
   private HasGears    gearsDelegate    = new ElectronicGears(...) ;
}

where the eclipse generate delegate methods will produce methods such as

   public void steerToRight( double value ) {
      steeringDelegate.steerToRight( value ) ;
   }
   ...
   public void brake( double value ) {
      brakesDelegate.brake( value ) ;
   }
 

As one can see, this now allows operations such as

   MyCar car ...
   ...
   car.brake( 3. ) ;
   car.steerToRight( 0.3 ) ;
 

that is, the car is now composed of its internals.

Exposing the delegates

In MATSim, we often expose the delegation, that is, the syntax is

  car.getBrakes().brake( 3. ) ;
  car.getSteering().steerToRight( 0.3 ) ;
 

This has the advantage that, if you extend the interfaces, you do not need to adapt every implementation.  It is, clearly, not an option if you want to write a class (such as a PlanStrategy) that is later inserted into the code – that has to fulfill the contract defined by the interface.


Warning: Table 'watchdog' is read only query: INSERT INTO watchdog (uid, type, message, severity, link, location, referer, hostname, timestamp) VALUES (0, 'php', '<em>Table &amp;#039;sessions&amp;#039; is read only\nquery: UPDATE sessions SET uid = 0, cache = 0, hostname = &amp;#039;38.107.179.230&amp;#039;, session = &amp;#039;&amp;#039;, timestamp = 1328355052 WHERE sid = &amp;#039;e972b2ab7dd755a2094beea8ac708f02&amp;#039;</em> in <em>/home01/vsp_access/matsimwww/includes/database.mysql.inc</em> on line <em>174</em>.', 2, '', 'http://matsim.org/node/516', '', '38.107.179.230', 1328355052) in /home01/vsp_access/matsimwww/includes/database.mysql.inc on line 174