5

I am going through Effective Java, Item-16 Favor composition over inheritance. I looked at the Forwarding class example below.

I am wondering what's the point of having a ForwardingSet class? InstrumentedSet can very well implement Set and have a private instance of it which invokes all the methods.

Is it to promote re-use and prevent redundancy if we end up having more InstrumentedSet like classes in the future which just need to do something in addition to the base behavior? Is it just future-proofing the design or is there something else to it that I am missing?

// Reusable forwarding class 
public class ForwardingSet<E> implements Set<E> {     
  private final Set<E> s;     
  public ForwardingSet(Set<E> s) { this.s = s; }     
  public void clear()               { s.clear();            }    
  public boolean contains(Object o) { return s.contains(o); }
...
}

// Wrapper class - uses composition in place of inheritance   
public class InstrumentedSet<E> extends ForwardingSet<E> {     
      private int addCount = 0;     
      public InstrumentedSet(Set<E> s) { super(s); } 
      @Override public boolean add(E e) {         
          addCount++;
          return super.add(e);
       }
       ...
    }
linuxNoob
  • 600
  • 2
  • 14
  • 30
  • 2
    Note, this refers to Effective Java 2nd edition. In 3rd edition, the item number for "Favor composition over inheritance" is changed to 18. – Olivier Grégoire Sep 15 '18 at 14:41

2 Answers2

7

Yes, ForwardingSet is a framework.

If you have to write several Sets that work with other Sets internally but provide different functionalities on top of the "vanilla" Set, you'd better write the common part once and not several times.

Joshua Bloch, in Effective Java refers to it as "composition", though the actual implementation looks more like the decorator pattern.

An actual implementation is readily available in Guava, as a class named ForwardingSet.

Is it to promote re-use and prevent redundancy if we end up having more InstrumentedSet like classes in the future which just need to do something in addition to the base behavior?

Yes.

Is it just future-proofing the design?

Yes.

or is there something else to it that I am missing?

No, you're not missing anything.

Olivier Grégoire
  • 33,839
  • 23
  • 96
  • 137
  • My next question is: Do we do this every time we think there might be a need to `decorate` the API with more than the default behavior? Like say APIs which on the face of it aren't screaming the need for re-use. Let's say retrieving and returning some items from the database. – linuxNoob Sep 15 '18 at 14:33
  • 1
    @linuxNoob No. Not every time, start thinking about refactoring into a `Forwarding...` class only when several wrappers are written. – Olivier Grégoire Sep 15 '18 at 14:39
  • 2
    @linuxNoob If the object being decorated implements a lot of methods, and you're only modifying the behavior of a few (if any), then having a delegate-only base class helps separate the delegation logic from the decoration logic, i.e. the base class only does delegation, so it doesn't really need to be tested and reviewed, and the subclass only does the decoration, so it needs to be tested and reviewed. The decoration logic will not "drown" in a sea of delegation logic. See also: [Separation of Concerns](https://en.wikipedia.org/wiki/Separation_of_concerns). – Andreas Sep 15 '18 at 14:41
4

Is it to promote re-use and prevent redundancy? Yes.
Is it just future-proofing the design? Yes.
Is there something else to it that I am missing? No.

The "forwarding" is commonly referred to as "delegation".
See: What is the purpose of a delegation pattern?

Some examples of Java classes with delegate-only implementations:

Andreas
  • 154,647
  • 11
  • 152
  • 247