Consider Bloch's Stack
class:
public class Stack {
private Object[] elements;
private int size = 0;
private final int DEFAULT_CAPACITY = 10;
public Stack() {
this.elements = new Object[DEFAULT_CAPACITY];
}
public void push (Object e) {
ensureCapacity();
elements[size++] = e;
}
public Object pop () {
if (size == 0) throw new IllegalStateException("Stack.pop");
Object result = elements[--size];
elements[size] = null;
return result;
}
private void ensureCapacity() {
if (elements.length == size) {
Object oldElements[] = elements;
elements = new Object[2*size + 1];
System.arraycopy(oldElements, 0, elements, 0, size);
}
}
}
Code an immutable version. Keep the same instance variables.
Follow Liskov's guidance for immutability.
We'll get to Bloch's rules later.
Specific items:
What happens to:
- the constructor implementation?
-
DEFAULT_CAPACITY
?
-
push()
?
-
pop()
?
-
ensureCapacity()
?
Now let's turn to the contract for this class.
- What is the contract for this class as a whole?
- What are the contracts for each method?
- What information should be documented by and for implementors?