Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Effective Java item 16 (2nd edition) - Is Forwarding class only used to allow re-use?

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);
       }
       ...
    }
like image 568
linuxNoob Avatar asked Sep 15 '18 14:09

linuxNoob


2 Answers

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:

  • java.io.FilterInputStream (and java.io.FilterOutputStream, java.io.FilterReader, java.io.FilterWriter)

    The class FilterInputStream itself simply overrides all methods of InputStream with versions that pass all requests to the contained input stream. Subclasses of FilterInputStream may further override some of these methods and may also provide additional methods and fields.

  • javax.servlet.ServletRequestWrapper (and javax.servlet.ServletResponseWrapper, javax.servlet.http.HttpServletRequestWrapper, javax.servlet.http.HttpServletResponseWrapper)

    Provides a convenient implementation of the ServletRequest interface that can be subclassed by developers wishing to adapt the request to a Servlet. This class implements the Wrapper or Decorator pattern. Methods default to calling through to the wrapped request object.

like image 39
Andreas Avatar answered Nov 15 '22 18:11

Andreas


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.

like image 61
Olivier Grégoire Avatar answered Nov 15 '22 18:11

Olivier Grégoire