Review
In class we saw that each type of collection has an interface (e.g. List
, Set
) and various implementations that implement those interfaces (e.g. ArrayList
/LinkedList
for List
and TreeSet
/HashSet
for Set
). We use interfaces to make our code more general; for example we can write code that works with any Set
rather than having to write it once to work for TreeSet
and another time for HashSet
.
In Java, interfaces are used to make the code more general by making a promise that any class that implements the interface is guaranteed to have those methods. In this reading, we will see how to write an interface and make your classes implement them.
Writing an interface
Writing an interface is very similar to writing a class, but you use the keyword interface
instead of class
.
For example, we are going to make an IntList
interface that acts like Java’s List
but to go along with our ArrayIntList
. We’ll see next week another way to implement an IntList
called a LinkedIntList
.
public interface IntList {
// TODO fill this in
}
Recall that an interface is a way of specifying “all classes that implement my interface are required to have these methods”. To require all classes that are IntList
s to have an add
method, we write the method header for the method we want without a body (since interfaces don’t provide implementations, only requirements). We would then write
public interface IntList {
public void add(int value); // notice ; instead of { } with method body
}
Now any class that claims to be an IntList
must have a method that matches the signature add(int)
. There are many other methods we probably want to make sure anyone who is an IntList
has, so we can add more method requirements as so:
public interface IntList {
public void add(int value);
public void add(int index, int value);
public boolean contains(int value);
public int get(int index);
public void remove(int index);
public int size();
}
Now that we have the IntList
interface, we can write methods that work with it! Remember that if we have a variable of type IntList
, we are allowed to call any of the methods required by the IntList
interface on that variable since Java will enforce that any class that implements the interface will have all the required methods.
For example if we wanted to write a method that took an IntList
and printed all the values in the list, we could write the following
public static void printList(IntList list) {
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
}
Now let’s try calling the printList
method.
public static void main(String[] args) {
ArrayIntList list = new ArrayIntList();
list.add(1);
list.add(2);
list.add(3);
printList(list);
}
Unfortunately we will end up getting a compiler error because Java doesn’t know that ArrayIntList
is an IntList
by default. We have to do something special in the ArrayIntList
class to tell Java that it has all the IntList
methods.
Making ArrayIntList
an IntList
We have all the methods we need implemented in ArrayIntList
(and some more!), we just need to tell Java that ArrayIntList
is actually an IntList
. To do that we just have to change the class header to
public class ArrayIntList implements IntList
This is telling Java that we promise to implement all the methods defined in IntList
. If we were to forget a method (say contains(int)
), then our class would not compile because it did not implement all the methods IntList
asked for!
After adding these two tokens, we are now able to call printList
passing in an ArrayIntList
. In fact, now that we have an interface for it, it would be better style to define the variable in the client code as
IntList list = new ArrayIntList();