Favor composition over inheritance is a one of the popular object
oriented design principle, which helps to create flexible and maintainable code
in Java and other object oriented languages. Many times I have seen people
suggesting use composition instead of inheritance, in fact my favorite books like
Head first Design Patterns, also
advocates this design principle. Head first books, has its own way of
explaining, why composition is better than inheritance and though its long its
quite interesting and informative. It was the first chapter of this book, which
helped me a lot on understanding this key OOPS concept. In this Java and OOPS tutorial,
I have tried to summarize my experience around composition and inheritance in
two main category, first, difference between composition and inheritance and second,
when to use Composition over inheritance in Java. I have already mentioned
about this design principle, in my list of 10 OOPS and SOLID design principles for
Java programmers, here we will take a more closer look.
Reasons to prefer Composition over Inheritance in Java

1) 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 called
composition. If you are following programming for interface than implementation
principle, and using type of base class as member variable, you can use
different Reader and Writer
implementation at different situation. You won’t get this flexibility by using
Inheritance, in case of extending a
class, you only get facilities which are available at compile time.
2) 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.
3) Many object oriented design patterns mentioned by Gang of Four in
there timeless classic Design Patterns: Elements of Reusable
Object-Oriented Software, favors Composition over Inheritance. Classical
examples of this is Strategy design pattern, where composition
and delegation is used to change Context’s behavior, without touching context
code. Since Context uses composition to hold strategy, instead of getting it
via inheritance, it’s easy to provide a new Strategy implementation at runtime.
Another good example of using composition over inheritance is Decorator design
pattern. In Decorator pattern, we don't
extend any class to add additional functionality, instead we keep an instance
of the class we are decorating and delegates original task to that class after
doing decoration. This is one of the biggest proof of choosing composition over
inheritance, since these design patterns are well tried and tested in different
scenarios and withstand test of time, keeping there head high.
4) 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. One example of inheritance making code fragile is method add() and addAll() from HashSet. Suppose,
If addAll() of HashSet is implemented by calling add() method and
you write a sub class of HashSet, which encrypt the content before inserting
into HashSet. Since there are only one methods add(), which can
insert object into HashSet you override these method and called your encrypt() method by
overriding add(). This automatically covers addAll() as well,
because addAll() is implemented using add(), it
looks very enticing.If you look closely you will see that this implementation is fragile, because its relied on super class behavior. If base
class wants to improve performance and implements addAll() without
calling add() method, below example will break.
public class
EncryptedHashSet extends HashSet{
.....
public boolean add(Object o) {
return super.add(encrypt(o));
}
}
If you have used Composition in favor of Inheritance you won't face this problem and your Class would have been more robust, because you are not relying on super class behavior any more. Instead you are using super class method for addition part and you will benefit with any improvement in addAll() as shown in below example:
public class
EncryptedHashSet implements Set{
private HashSet container;
public boolean add(Object o) {
return container.add(encrypt(o));
}
public boolean addAll(Collection c) {
return conatainer.add(encrypt(c));
}
.......
}
5. Another reason of favoring Composition over inheritance is
flexibility. If you use Composition you are flexible enough to replace
implementation of Composed class with better and improved version. One example
is using Comparator class which
provides compare functionality. if your Container object contains a Comparator instead of
extending a particular Comparator for comparing , its easier to
change the way comparison is performed by setting different type of Comparator to
composed instance, while in case of inheritance you can only have one comparison behavior on runtime, You can not change it runtime.
There are many more reasons to favor
Composition over inheritance, which you will start discovering once you
start using design patterns in Java. In nutshell favoring Composition results
in more flexible and robust class than using inheritance. Though there are
certainly some cases where using Inheritance makes much sense like when a
genuine parent child relation exists, but most of time it makes sense to favor
composition over inheritance for code reuse. There is an item of this topic on
my another favorite book, Effective Java, which has also
helped me to understand this concept better, you may want to look that as well.
No comments:
Post a Comment