Infolinks In Text Ads

Favor Composition Over Inheritance in Java

 Inheritance
  • Method of reuse in which new functionality is obtained by
    extending the implementation of an existing object
  •  The generalization class (the superclass) explicitly captures the
    common attributes and methods
  • The specialization class (the subclass) extends the implementation
    with additional attributes and methods
Advantages and Disadvantages Of Inheritance:
Advantages:
  • New implementation is easy, since most of it is inherited
  • Easy to modify or extend the implementation being reused
Disadvantages:
  • Breaks encapsulation, since it exposes a subclass to implementation details
    of its superclass
  • "White-box" reuse, since internal details of superclasses are often visible to
    subclasses
  • Subclasses may have to be changed if the implementation of the superclass
    changes
  • Implementations inherited from superclasses can not be changed at runtime
Advantages and Disadvantages Of  Comoposition:
Advantages :
  • Contained objects are accessed by the containing class solely through their
    interfaces
  • "Black-box" reuse, since internal details of contained objects are not visible
  • Good encapsulation
  • Fewer implementation dependencies
  • Each class is focused on just one task
  • The composition can be defined dynamically at run-time through objects
    acquiring references to other objects of the same type
Disadvantages :
  • Resulting systems tend to have more objects
  • Interfaces must be carefully defined in order to use many different objects
    as composition blocks

Inheritance vs Composition Example
The example that i am going to discuss with you guys, comes from Effective java by Joshua
Bloch.Suppose we want a variant of HashSet that keeps track of the number of attempted insertions. So we subclass HashSet as follows:



package aurangzeb.utk.com;

import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;

public class InstrumentedHashSet extends HashSet {

      // The number of attempted element insertions
      private int addCount = 0;

      public InstrumentedHashSet(Collection c) {
            super(c);
      }

      public InstrumentedHashSet(int initCap, float loadFactor) {
            super(initCap, loadFactor);

      }

      public InstrumentedHashSet() {
            // TODO Auto-generated constructor stub
      }

      public boolean add(Object o) {
            addCount++;
            return super.add(o);
      }

      public boolean addAll(Collection c) {
            addCount += c.size();
            return super.addAll(c);
      }

      public int getAddCount() {
            return addCount;
      }

Now lets test the above example and see the result which is 6,and the expected result should be 3,so we are getting the wrong output because of using inheritance.

why we are not getting the expected output the reason is obvious It’s because the internal implementation of addAll() in the HashSet superclass itself invokes the add() method. So first we add 3 to addCount in InstrumentedHashSet’s addAll(). Then we invoke HashSets addAll(). For each element, this addAll() invokes the add() method, which as overridden by InstrumentedHashSet adds one for each element. The result: each element is double counted.

There are several ways to fix the above problem
  •  There are several ways to fix this, but note the fragility of our subclass. Implementation details of our superclass affected the operation of our subclass. 
  • The best way to fix this is to use composition. Let’s write an
    InstrumentedSet class that is composed of a Set object. Our
    InstrumentedSet class will duplicate the Set interface, but all Set operations will actually be forwarded to the contained Set object.
  • InstrumentedSet is known as a wrapper class, since it wraps an
    instance of a Set object.
  • This is an example of delegation through composition!

package aurangzeb.utk.com;

import java.util.Collection;
import java.util.Iterator;
import java.util.Set;

public class InstrumentedSet implements Set {
      private final Set s;
      private int addCount = 0;
      public InstrumentedSet(Set s) {this.s = s;}
      public boolean add(Object o) {
      addCount++;
      return s.add(o);
      }
      public boolean addAll(Collection c) {
      addCount += c.size();
      return s.addAll(c);
      }
      public int getAddCount() {return addCount;}
      @Override
      public void clear() {
            // TODO Auto-generated method stub
           
      }
      @Override
      public boolean contains(Object arg0) {
            // TODO Auto-generated method stub
            return false;
      }
      @Override
      public boolean containsAll(Collection arg0) {
            // TODO Auto-generated method stub
            return false;
      }
      @Override
      public boolean isEmpty() {
            // TODO Auto-generated method stub
            return false;
      }
      @Override
      public Iterator iterator() {
            // TODO Auto-generated method stub
            return null;
      }
      @Override
      public boolean remove(Object arg0) {
            // TODO Auto-generated method stub
            return false;
      }
      @Override
      public boolean removeAll(Collection arg0) {
            // TODO Auto-generated method stub
            return false;
      }
      @Override
      public boolean retainAll(Collection arg0) {
            // TODO Auto-generated method stub
            return false;
      }
      @Override
      public int size() {
            // TODO Auto-generated method stub
            return 0;
      }
      @Override
      public Object[] toArray() {
            // TODO Auto-generated method stub
            return null;
      }
      @Override
      public Object[] toArray(Object[] arg0) {
            // TODO Auto-generated method stub
            return null;
      }
}


Note several things: This class is a Set It has one constructor whose argument is a Set The contained Set object can be an object of any class that implements the Set interface (and not just a HashSet)  This class is very flexible and can wrap any preexisting Set object.

References: Effective Java,OO Design Principles.


Newer Post Older Post

Leave a Reply

Powered by Blogger.