|
Another thing we can notice in the getEnumerator code:
We only create the Enumerator instance, and return it. We never make
any other references to that Enumerator instance inside getEnumerator.
We often make use of temporary variables in Java. For example, we can
say something like:
process( new Processee() );
where the parameter being passed has no local name -- it's a temporary
variable.
We can do the same thing with a local class -- turn it into an anonymous
class!
So, that's what I did. Here's what the new Stack class looks like with
an anonymous class:
package anonymousClasses;
import java.util.Enumeration;
/**
* Stack implements a simple stack of integers
*/
public class Stack
{
/**
* Creates a stack of specified number of elements
*/
public Stack(int size)
{
m_stackData = new int[size];
}
/**
* Pushes an integer value on the stack,
* or throws an exception, if insufficient space
*/
public void push(int value) throws IllegalStateException
{
if (m_next >= m_stackData.length)
throw new IllegalStateException("Stack full");
m_stackData[m_next++] = value;
}
/**
* Returns whether the stack is currently empty
*/
public boolean isEmpty()
{
return (m_next == 0);
}
/**
* Pops the top int value off the stack,
* or throws an exception if the stack is empty
*/
public int pop() throws IllegalStateException
{
if (isEmpty())
throw new IllegalStateException("Stack empty");
return m_stackData[--m_next]; // top item on stack
}
/**
* Returns the current size of the stack
*/
public int getStackSize()
{
return m_next;
}
/**
* Returns the maximum size of the stack
*/
public int getMaxStackSize()
{
return m_stackData.length;
}
/**
* Return the value of the specified item in the stack
* or throws an exception if the index specified is invalid.
*/
private int get(int index) throws IllegalArgumentException
{
if (index < 0 || index >= getStackSize())
throw new IllegalArgumentException("index = " + index);
return m_stackData[index];
}
/**
* Returns an instance of the Enumerator class to the caller
* as an Enumeration. This is known as an "opaque" class.
* All the caller needs to know is that the class being returned
* implements the Enumeration interface.
*/
public Enumeration getEnumerator()
{
/**
* An anonymous class to iterate through an instance of this Stack
*/
return new Enumeration()
{
/**
* Returns whether there are more elements
*/
public boolean hasMoreElements()
{
return m_current < getStackSize() - 1;
}
/**
* Returns the next element
*/
public Object nextElement()
{
return get(++m_current);
}
private int m_current = -1; // Position "before" first stack element
};
}
private int[] m_stackData;
private int m_next = 0; // Index of last item in stack
}
|
Notice that we appear to be creating a new instance of Enumeration, which is
actually an interface. However, that's just an artifact of the syntax.
In fact, we are really creating an instance of a class (that has no name --
it's anonymous!) that implements the Enumeration interface.
|