Using Interfaces and Inner Classes Together

Introduction

Java 1.1 has a new feature called inner classes. An inner class is defined within another class or within a method of some class. As such it provides local services at the level at which it is defined. Inner classes may be used to define functionality at the point at which it is to be used and to hide it from other points in the program.

Java interfaces are used to define protocols for user defined functionality. Interfaces define first class types and as such can be used as the types of variables and parameters. An object of any class implementing an interface is compatible with a variable or parameter of that interface type. Interfaces may be used to give a form of generic programming and a form of multiple inheritance.

Since classes may be defined as inner classes to interfaces, we can use inner classes to provide default or alternate implementations for interfaces.

An Example

In the following example we see the definition of a Stack interface with the usual push and pop operations. Defined within this interface are two different implementations: a dense (array) implementation, and one based on linked lists. Within the linked class is a further inner class to define the node class out of which the linked list is built.


interface Stack 
{	public void push(Object o);
	public Object pop();
	public Object top();
	public boolean empty();
	public boolean full();

	public class Dense implements Stack
	{	public Dense (int n)
		{	imp = new Object[n];
			capacity = n;
		}

		public void push(Object o)
		{	imp[size++] = o;
		}
		. . .
		private Object []  imp; // Array implementation
		private int size = 0;
		private int capacity = 0;
	}

	public class Linked implements Stack
	{	public Linked (){}

		public void push(Object o)
		{	head = new Node(o, head);
		}
		...
		private Node head = null; // Linked list

		private class Node
		{	public Node(Object val, Node nextNode)
			{	value = val;
				next = nextNode;
			}
			...
			private Object value;
			private Node next;
		}
	}

}

We can then get a linked stack by declaring


Stack S = new Stack.Linked();

Likewise we can get a new dense stack with a capacity of 100 with


Stack S = new Stack.Dense(100);


On the other hand, if we decide that neither of these implementations is adequate for the problem at hand, we can always define a new class that implements the Stack interface.

   Note that inner classes can use the private members of the classes they are 
   contained within and "outer" classes can use the private members of the 
   classes that are inner to them.

We could also define a public inner Enumeration class within Stack.Dense and Stack.Linked to provide the enumeration facility for each of these classes.

Acknowledgment

Thanks to Tim Budd for this suggestion.