// Joshua Bloch
// Effective Java
// Programming Language Guide
// Addison-Wesley, 2001
// Item 14: Favor composition over inheritance

// Broken - Inappropriate use of inheritance!
public class InstrumentedHashSet extends HashSet {
    // The number of attempted element insertions
    private int addCount = 0;

    public InstrumentedHashSet () {
    }

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

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

    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;
    }
}

// InstrumentedHashSet s = new InstrumentedHashSet();
// s.addAll(Arrays.asList(new String[] {"Snap", "Crackle", "Pop"}));
// s.getAddCount() returns 6, not 3
// Reason: addAll in class HashSet internally call add,
// which we overrode.

// Wrapper class - uses composition in place of inheritance
public class InstrumentedSet implements Set {
    private final Set s;
    private in 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;
    }

    // Forwarding methods
    public void clear()               { s.clear ();           }
    public boolean contains(Object o) { return s.contains(o); }
    public boolean isEmpty()          { return s.isEmpty();   }
    // ...
    public String toString ()         { return s.toString();  }
}
