Introduction
We have often heard that composition is better than inheritance. Why is it so? First of all, how is one different from the other, and what are the similarities in them?
Let's say we are writing simulation software for Rocket Launching systems that are to be supplied to different countries. Now these different countries can use them as they want.
Example. The code for our launching system is below.
using System;
public class Launcher
{
public bool LaunchMissile()
{
Console.WriteLine("Missile launched");
return true;
}
}
public class SurfaceToAirMissileLauncher : Launcher
{
}
Now, country A uses this code to launch missiles as follows.
Example
static void Main(string[] args)
{
SurfaceToAirMissileLauncher staLauncher = new SurfaceToAirMissileLauncher();
bool isLaunched = staLauncher.LaunchMissile();
}
This is how Inheritance is used. The various launchers can reuse the base Launcher class code to launch missiles.
The same thing can be achieved by using Composition, where base class functionality is encapsulated inside the main concrete class.
Example. The code for that is below.
public class SurfaceToAirMissileLauncher
{
private Launcher launcher = new Launcher();
public bool LaunchMissile()
{
return launcher.LaunchMissile();
}
}
The client UI code remains the same.
Now, due to our superb code, our patented launching software has become famous, and another country, B, wants to use it. But they had a condition that instead of launching the missile through base class, they would want to get an instance of a missile. Now it's up to them what they want to do with it. They might add some nuclear material to it, modify it to increase its range, or do whatever they might like. So another Missile object comes into the picture.
Example
public class Missile
{
private bool isLaunched;
public bool IsLaunched
{
get { return isLaunched; }
set { isLaunched = value; }
}
public Missile(bool isLaunched)
{
IsLaunched = isLaunched;
}
}
The base class function has changed to.
Example
public class Launcher
{
public Missile LaunchMissile()
{
Console.WriteLine("Missile returned");
return new Missile(true);
}
}
Now it returns a missile instead of launching it. So now, if we rely on inheritance, the client code of country A would break since the method signature has changed from what is being used in its UI.
However, if country A had used composition instead, the code would not break. Only the derived class function would need to accommodate the newly changed behavior of the base class. To accommodate this.
we need to change our derived class code function "LaunchMissile."
Example
public class SurfaceToAirMissileLauncher
{
private Launcher launcher = new Launcher();
public bool LaunchMissile()
{
Missile missile = launcher.LaunchMissile();
return missile.IsLaunched;
}
}
Hence, the client code of country A would still work.
Example
static void Main(string[] args)
{
SurfaceToAirMissileLauncher staLauncher = new SurfaceToAirMissileLauncher();
bool isLaunched = staLauncher.LaunchMissile();
}
On the other hand, country B which was insisting on getting a missile, would still get a missile from the base class.
So through this simple example, we see how the composition is favored over inheritance to maintain compatibility and where there is a possibility that the functionality might change in the future.