Why is composition favored over inheritance

Object-Oriented Programing (OOP) has too well known candidates for the reuse of functionality: Inheritance (whitebox reuse) and Composition (blackbox reuse). Just to revise, composition and Inheritance are ways to reuse code to get additional functionality. In Inheritance, a new class, which wants to reuse code, inherit an existing class, known as super class. This new class is then known as sub class. On composition, a class, which desire to use functionality of an existing class, doesn’t inherit, instead it holds a reference of that class in a member variable, that’s why the name composition. Inheritance and composition relationships are also referred as IS-A and HAS-A relationships. Because of IS-A relationship, an instance of sub class can be passed to a method, which accepts instance of super class. This is a kind of polymorphism, which is achieved using Inheritance. A super class reference variable can refer to an instance of sub class. By using composition, you don’t get this behavior, but still it offers a lot more to tild the balance in its side.

One reason of favoring Composition over Inheritance in Java is fact that Java doesn’t support multiple inheritance. Since you can only extend one class in Java, but if you need multiple functionality like e.g. for reading and writing character data into file, you need Reader and Writer functionality and having them as private members makes your job easy that’s composition.

Composition offers better testability of a class than Inheritance. If one class is composed of another class, you can easily create Mock Object representing composed class for sake of testing. Inheritance doesn’t provide this luxury. In order to test derived class, you must need its super class. Since unit testing is one of the most important thing to consider during software development, especially in test driven development, composition wins over inheritance

Though both Composition and Inheritance allows you to reuse code, one of the disadvantage of Inheritance is that it breaks encapsulation. If sub class is depending on super class behavior for its operation, it suddenly becomes fragile. When behavior of super class changes, functionality in sub class may get broken, without any change on its part

Example
Lets say we are writing simulation software for Rocket Launching systems which are to be supplied to different countries. Now these different countries can use them as they want it. The code for our launching system is below:

public class Launcher 
{ 
    public bool LaunchMissile() 
    { 
        Console.WriteLine("Missile launched"); 
        return true; 
    }
 
}
public class SufraceToAirMissileLauncher : Launcher
{
 
}

Now, country A uses this code to launch missile as follows:

static void Main(string[] args) 
{ 
    SufraceToAirMissileLauncher staLauncher = new SufraceToAirMissileLauncher(); 
    bool isLaunched = staLauncher.LaunchMissile();
    Console.ReadLine();
}

This is how Inheritance is used. The various launchers can reuse the base Launcher class code to launch missile.

The same thing can be achieved by using Composition where base class functionality is encapsulated inside the main concrete class. The code for that is below:

public class SufraceToAirMissileLauncher 
{ 
    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 had 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 on it or modify it to increase its range or do whatever they might like. So another Missile object comes into the picture.

public class Missile 
{ 
    private bool isLaunched; 
    public bool IsLaunched 
    { 
        get
        {
            return isLaunched; 
        } 
        set 
        { 
            isLaunched = value; 
        } 
    } 
    public Missile(bool isLaunched) 
    { 
        IsLaunched = IsLaunched;
    } 
}

And the base class function has changed to:

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 the country A had used composition instead, the code will not break. Only the derived class function would need to accommodate the new changed behavior of the base class. To accommodate this, we need to change our derived class code function “LaunchMissile” as:

public class SufraceToAirMissileLauncher
{
    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:

static void Main(string[] args) 
{ 
    SufraceToAirMissileLauncher staLauncher = new SufraceToAirMissileLauncher(); 
    bool isLaunched = staLauncher.LaunchMissile();
    Console.ReadLine();
}

On the other hand country B which was insisting on getting a missile would still get 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 future.

Source Code

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s