Item 18: Favor composition over inheritance

Inheritance violates encapsulation unless the superclass’s authors have designed it specifically for the purpose of being extended

The superclass’s implementation may change from release to release, and if it does, the subclass may break, even though its code has not been touched. As a consequence, a subclass must evolve in tandem with its superclass, unless the superclass’s authors have designed and documented it specifically for the purpose of being extended.

How to use composition and forwarding technique

Let’s say you want to extend the functionality of the Set interface.

  1. Create a Forwarding class
  • Step 1. Composition
    Give your class a private field that references an instance of the existing class (Set)
//your forwarding class
public class ForwardingSet<E> implements Set<E> {
 	private final Set<E> s;
 	...
}

  • Step 2. Forwarding
    Each instance method in the new class invokes the corresponding method on the contained instance of the existing class and returns the results
    ...
	@Override
	public boolean add(E e) {
		return s.add(e);
	}

	@Override
	public boolean addAll(Collection<? extends E> c) {
		return s.addAll(c);
	}
	...
  1. Extend the forwarding class
public class InstrumentedSet<E> extends ForwardingSet<E> {

	// The number of attempted element insertions
	private int addCount = 0;
    
        // constructor 
	public InstrumentedSet(Set<E> s) {
		super(s);
	}

	@Override
	public boolean add(E e) {
	...your new implementation ...
	}
	
	....other overriden methods...
	
	//your new method
	public int getAddCount() {
		return addCount;
	}
  1. And it is ready to use
	InstrumentedSet<String> s2 = new InstrumentedSet<>(new TreeSet<>());
	s2.addAll(Arrays.asList("Snap", "Crackle", "Snap"));
	System.out.println("Total: "  + s2.getAddCount());

Leave a Reply

Your email address will not be published. Required fields are marked *