How do you implement reuse via the delegation pattern in Java? Show held fields and forwarding methods.
answer
- Private final field + constructor injection
- Forwarding method = one-line call-through
- Implement same interface, override only what changes
- ForwardingSet + InstrumentedSet = no double-count
- Boilerplate fix: reusable Forwarding* base or IDE-generated
basics
~10 sKeep the other object in a private field, and write methods that simply call the matching method on that held object. Those one-line pass-through methods are the forwarding methods.
solid answer
~50 sDelegation is the mechanical technique that implements composition-for-reuse. The composing class stores the collaborator in a private (often final) field, usually injected through the constructor. For each operation you want to expose, you write a forwarding method whose body just calls the same operation on the held object and returns its result. The wrapper's own public surface is whatever methods you choose to forward — typically a subset of the delegate's API, which is how composition avoids leaking the full parent API that inheritance would. A common, powerful variant is the wrapper that *implements the same interface* as its delegate (e.g. implement Set and forward to a held Set), so the wrapper is drop-in compatible while adding behavior. To cut boilerplate you can write a reusable Forwarding* base class that forwards everything, then subclass it to override just the methods you want to change.
code
java · 37 linesimport java.util.*;
// Reusable forwarding base: implements Set, delegates everything.
class ForwardingSet<E> implements Set<E> {
private final Set<E> s;
ForwardingSet(Set<E> s) { this.s = s; }
public boolean add(E e) { return s.add(e); }
public boolean addAll(Collection<? extends E> c) { return s.addAll(c); }
public int size() { return s.size(); }
public boolean isEmpty() { return s.isEmpty(); }
public boolean contains(Object o) { return s.contains(o); }
public Iterator<E> iterator() { return s.iterator(); }
public Object[] toArray() { return s.toArray(); }
public <T> T[] toArray(T[] a) { return s.toArray(a); }
public boolean remove(Object o) { return s.remove(o); }
public boolean containsAll(Collection<?> c) { return s.containsAll(c); }
public boolean removeAll(Collection<?> c) { return s.removeAll(c); }
public boolean retainAll(Collection<?> c) { return s.retainAll(c); }
public void clear() { s.clear(); }
}
// Thin wrapper that adds counting; works over ANY Set, no double-count bug.
class InstrumentedSet<E> extends ForwardingSet<E> {
private int addCount = 0;
InstrumentedSet(Set<E> s) { super(s); }
@Override public boolean add(E e) { addCount++; return super.add(e); }
@Override public boolean addAll(Collection<? extends E> c) { addCount += c.size(); return super.addAll(c); }
int getAddCount() { return addCount; }
}
public class Demo {
public static void main(String[] args) {
InstrumentedSet<String> s = new InstrumentedSet<>(new HashSet<>());
s.addAll(List.of("a", "b", "c"));
System.out.println(s.getAddCount()); // 3 (not 6)
}
}go deeper
Can store a collaborator in a field and write simple methods that call it; understands the field is the delegate.
Implements constructor-injected delegation, exposes a chosen subset of the delegate's API, and writes an interface-preserving wrapper.
Builds a reusable Forwarding* base to manage boilerplate, explains why the wrapper avoids inheritance's self-use bug, and ties it to the Decorator pattern.
Decides between hand-written forwarders, generated delegation, and dynamic proxies based on API width, evolution, and performance; defines composition seams for a codebase.
## What delegation is **Delegation** is the implementation technique that turns the *principle* "favor composition over inheritance" into actual code. The idea: rather than inheriting behavior, your class **holds** a reference to an object that already has the behavior, and **delegates** (hands off) work to it. There are two moving parts: - **The held field (the delegate):** a field whose type is the collaborator. Keep it `private` so callers can't reach it directly, and usually `final` so it can't be reseated after construction. Inject it through the constructor so the wrapper doesn't hard-code which concrete collaborator it uses. - **Forwarding methods:** for each capability you expose, write a method that simply calls the corresponding method on the held object and returns the result. These are typically one-liners. ```java public final class Playlist { private final List<Song> songs; // held delegate public Playlist(List<Song> songs) { // constructor injection this.songs = songs; } public void add(Song s) { songs.add(s); } // forwarding method public int size() { return songs.size(); } // forwarding method // NOTE: we deliberately do NOT forward, say, remove(int) — we choose the surface. } ``` `Playlist` reuses `List`'s behavior without being a `List`. Callers see only `add` and `size`; they cannot call `clear()` or `get(int)` unless `Playlist` chooses to forward them. That selective exposure is exactly what inheritance cannot give you (a subclass inherits the parent's *entire* public API). ## The interface-preserving wrapper (the strong form) The most useful flavor of delegation is when the wrapper **implements the same interface** as the thing it wraps and forwards every method, *then overrides only what it wants to change*. This is the basis of the *Decorator* pattern and of Joshua Bloch's `InstrumentedSet` example. ```java import java.util.*; public class ForwardingSet<E> implements Set<E> { private final Set<E> s; // held delegate public ForwardingSet(Set<E> s) { this.s = s; } public boolean add(E e) { return s.add(e); } public boolean addAll(Collection<? extends E> c) { return s.addAll(c); } public int size() { return s.size(); } public boolean isEmpty() { return s.isEmpty(); } public boolean contains(Object o) { return s.contains(o); } public Iterator<E> iterator() { return s.iterator(); } public Object[] toArray() { return s.toArray(); } public <T> T[] toArray(T[] a) { return s.toArray(a); } public boolean remove(Object o) { return s.remove(o); } public boolean containsAll(Collection<?> c) { return s.containsAll(c); } public boolean removeAll(Collection<?> c) { return s.removeAll(c); } public boolean retainAll(Collection<?> c) { return s.retainAll(c); } public void clear() { s.clear(); } } ``` Now the *added behavior* lives in a thin subclass of the forwarder: ```java 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); // forwards to the delegate } @Override public boolean addAll(Collection<? extends E> c) { addCount += c.size(); return super.addAll(c); } public int getAddCount() { return addCount; } } ``` Because the delegate's `addAll` is *its own* concern (the wrapper never relies on the delegate calling `add` internally), there is **no double-counting** bug — the very bug that the naive `extends HashSet` version suffers from. And `InstrumentedSet` works over *any* `Set` (HashSet, TreeSet, a synchronized set…), because it wraps the `Set` interface rather than a concrete class. ## Reducing the boilerplate The obvious cost is writing all those forwarding methods. Standard ways to manage it: - Write the `Forwarding*` base class **once** and reuse it for many decorators (as above). - Let your IDE generate delegate methods (IntelliJ/Eclipse both have "Generate › Delegate Methods"). - For some use cases, a dynamic `java.lang.reflect.Proxy` can forward generically (at the cost of reflection). ## Key terms - **Delegate / held object:** the collaborator stored in a field. - **Forwarding method:** a method that just calls through to the delegate. - **Constructor injection:** passing the delegate in via the constructor instead of `new`-ing it inside. - **Wrapper / Decorator:** an object that implements the same interface as the thing it holds and adds/alters behavior.
- Why does the InstrumentedSet wrapper avoid the double-counting bug that the HashSet subclass has?The wrapper counts in its own addAll and then forwards to the delegate's addAll; it never assumes the delegate's addAll calls its add. With inheritance, the subclass's addAll calls the inherited (and overridden) add, so each element is counted once by addAll and again by add.
- What design pattern is the interface-preserving forwarding wrapper most associated with?Decorator — it implements the same interface as the wrapped object and adds behavior transparently, so it can be used anywhere the original is expected and decorators can be stacked.
saying these in an interview costs you the question
- Making the held field public or non-final without reason, defeating encapsulation.
- Forwarding the entire API blindly when the point is to expose a chosen subset.
- Claiming delegation needs reflection — plain method calls suffice; reflection/Proxy is just one optional shortcut.
- Re-creating the inheritance double-count bug by having the wrapper rely on the delegate's internal self-use.