You may probably want to check Composition over inheritance
To favour composition over inheritance is a design principle that
gives the design higher flexibility, giving business-domain classes
and more stable business domain in the long term. In other words,
HAS-A can be better than an IS-A relationship
Check the answer of aleemb in a related post in which he explains the difference with code example
Here is a useful link which explains why prefer composition 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. 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));
}
.......
}