public abstract class Collection { public static class Pair { Object x; Collection y; Pair(Object theX, Collection theY) { x = theX; y = theY; } } /* These are *abstract* methods that our concrete subclasses will * have to implement. */ public abstract boolean isEmpty(); public abstract Collection addElem( Object x ); public abstract Collection.Pair anyElem(); /* These are *concrete* methods that are shared amongst all of our * subclasses. Thus we have automatic code reuse. */ public Collection addAll(Collection other_collection) { if (other_collection.isEmpty()) { return this; } else { Pair val_and_other_rest = other_collection.anyElem(); Object val = val_and_other_rest.x; Collection other_rest = val_and_other_rest.y; return this.addElem(val).addAll( other_rest ); } } public String toString() { return "( " + this.toItemsString() + ")"; } private String toItemsString() { if (this.isEmpty()) { return ""; } else { Pair val_and_other_rest = this.anyElem(); Object val = val_and_other_rest.x; Collection other_rest = val_and_other_rest.y; return (val.toString() + " " + other_rest.toItemsString()); } } }