Interfaces

An interface in Java is like a class that hasn’t been implemented yet. An interface contains a list of method headers, none of which are implemented. It is a way to list the features you want in a particular class without yet deciding how to implement them. Interfaces are very useful with data structures because we can list the functionality we’d like the data structure to have, and then implement them in several different ways.

Declaring an interface

Here’s a sample interface:

public interface ArrayCollection 
{
    void add(Object elem);
    void print();
}

This interface should be stored in the file ArrayCollection.java. This interface defines what functionality we’d like a collection of general elements to have. We don’t know exactly how we’re going to implement this collection, but we do know that we want to be able to add elements and print elements. Notice that we do not include visibility modifiers in an interface (they are all public by default).

Implementing an interface

Of course, we do eventually have to write code for array collections, or we won’t be able to use the interface. To do this, we write a class that implements the ArrayCollection interface. If a class implements an interface, then it must implement every method defined in the interface. The method headers in the class must look EXACTLY like the method headers in the interface.

First, we’ll implement the ArrayCollection interface using the by storing all elements added in an array (up to the maximum size):

public class ArrayList implements ArrayCollection 
{
    private Object[] arr;
    private int size;

    public ArrayList(int max) 
    {
        arr = new Object[max];
        size = 0;
    }

    public void add(Object elem) 
    {
        //Don't add if we've reached our max size
        if (size == arr.length) return;
    
        arr[size] = elem;
        size++;
    }

    public void print() 
    {
        for (int i = 0; i < size; i++) 
        {
            System.out.println(arr[i].toString());
        }
    }
}

Similarly, we can implement the ArrayCollection interface using by only storing each unique element added (up to the maximum size):

public class ArrayList implements ArrayCollection 
{
    private Object[] arr;
    private int size;

    public ArrayList(int max) 
    {
        arr = new Object[max];
        size = 0;
    }

    public void add(Object elem) 
    {
        //Don't add if we've reached our max size
        if (size == arr.length) return;

        //Check if elem is already in array
        for (int i = 0; i < size; i++)
        {
            if (val.equals(elem)) return;
        }
    
        //Now add elem (no duplicates)
        arr[size] = elem;
        size++;
    }

    public void print() 
    {
        for (int i = 0; i < size; i++) 
        {
            System.out.println(arr[i].toString());
        }
    }
}

Because ArrayCollection is an interface, we can’t create a new ArrayCollection object. However, we can store either an ArrayList or an ArraySet object in an ArrayCollection variable:

ArrayCollection coll = new ArrayList();
  • OR -
ArrayCollection coll = new ArrayCollection();

Then, we can call the ArrayCollection methods:

coll.add(2);
coll.add(2);

If we created an ArrayList object, then the 2 would be added twice. If we created an ArraySet object, the 2 would only be added once (since no duplicates are allowed). Thus we can very quickly change our functionality by creating an ArraySet or ArrayList, but the code using the collection would remain the same.