Java Notes‎ > ‎

Interfaces


[This material taken largely from Walter Savitch, Absolute Java, Addison Wesley, 2004. Ch. 13]

Definition and Motivation

An interface is a set of methods that any class that implements the interface must have. It essentially provides a sort of contract for use, guaranteeing which methods will be present and what their parameters will be.

Interfaces are Java's way of providing much of the power of multiple inheritance without the potential confusion of multiple bases classes having conflicts between method names.

An interface is not a class, but is a type that can be satisfied by any class that implements the interface. We can have variables (e.g. arrays, references) of type interface, but we can't have objects (i.e. created using new) of type interface. It is similar to an abstract class in that we can create subclasses of it, but not instances of it.

First Example: Sort

Consider a class called Student, where each student has a String name and int id. If we store these in an ArrayList, we get to take advantage of the List Interface implemented by ArrayList. The Collections class sort routine expects a parameter of type List, which ArrayList satisfies because it implements that Interface. It is a List.

The Comparable Interface

We can develop a class that will sort objects of any type, as long as we know how to compare them. (If you are familiar with C, you could do this in C by passing a pointer to a compare function as a parameter to your sort routine.) Since this need is so common in Java, it is defined as an interface called Comparable. If you will need to compare objects of a particular type, you should implement Comparable to guarantee that your compareTo() method will be compatible with built-in Java classes that expect it to exist (e.g. sort on a List, sort on a Object[] ). All the Java primitive class types (e.g. IntegerDoubleCharacter, etc.) implement Comparable. Note that primitive types do not implement any interfaces (e.g. primitive type int != Integer class).

Your implementation of public int compareTo( Object other) should implement the semantics (the meaning) that it returns:

  • a negative number if the calling object "comes before" the parameter other
  • a zero if the calling object "equals" the parameter other
  • a positive number if the calling object "comes after" the parameter other.

Example using the Comparable Interface

Consider the code to do a generalized selection sort. This code receives an array of any type, as long as the array type implements interface Comparable. Implementing this interface guarantees a definition of compareTo(), which through polymorphism will match to the compareTo() method in the appropriate class. Class GeneralizedSelectionSort shows both the sort() method, as well as a method indexOfSmallest(). We can test this with a driver called ComparableDemo, which calls the GeneralizedSelectionSort sort() method with arrays of different types. We could similarly sort an array of our own type (e.g. Employee, Date, or even PlayingPiece) if our own class both implements Comparable and defines compareTo().

Illustrating the Mechanism

Consider creating an interface of our own called OrderedAny class that implements this interface will have to also implement its methods precedes() and follows(). The definition of the interface itself is like a class definition, except it uses the word interface instead of the word class, and it only lists the method headers, followed by a semicolon. The interface and its methods must all be public. Note that the types of parameters are of type Object so that this interface can be used with any other class.

A class can use the interface Ordered by adding the words
     implements Ordered
after the header line of the class declaration. We can see an example of this with an OrderedHourlyEmployee class that extends HourlyEmployee and also implements the Ordered interface. In particular note the interface methods precedes() and follows() where the parameter is cast from type Object into the correct type.

Simplifying an Interface using an Adapter Class

Remember that to implement an interface, we must provide the definitions (not just declarations) for all its methods. This may be inconvenient in some situation where there are many methods in the interface, but we really only care about one or two of them. One example is the MouseInputListener interface that has methods for mouseClicked, mouseEntered, mouseExited, mousePressed, mouseReleased, even though we might only want to give the definition for mousePressed. By default you would have to give definitions for all of them, even if the bodies of the definitions are empty. (Details of this are given separately in the notes under the Swing topic.)

One way around this is to make an intermediary adapter class that implements all the methods from the interface with an empty body. Then your concrete class extends this intermediary adapter class, overriding only the methods that you wish to implement. Examples of this are MouseAdapter implementing MouseListener, and KeyAdapter implementing KeyListener.

An example of such an intermediary class accompanying the above HourlyEmployee example is MyAbstractClass, where it implements the Ordered interface, but only gives the definition for the precedes() method, leaving the definition of the follows() method for its child concrete class.

Extending an Interface

Similar to a class extending its superclass, an interface can be created that extends (a.k.a. derives from) another interface. An example of this is the ShowablyOrder interface extending the Ordered interface. A concrete class implementing ShowablyOrdered will need to give a definition for methods precedes() and follows() from the Ordered interface, as well as a definition for method showOneWhoPrecedes() from the ShowablyOrdered interface

Other uses of Interfaces

Sharing Constants: 

        An interface can be used to collect a set of constants that may be used across multiple classes. For instance, we could define interface MonthNumbers giving constants to every month name(JANUARY = 1, ...). Any class implementing this interface (e.g. DemoMonthNumbers) will automatically have access to these constants, e.g. being able to use JANUARY and the value 1 interchangeably. Though the constants are public static final, the specifiers public static will be assumed if left off, as in this version.

Serializable:

        This interface has no method headings or defined constants, but is used as a type tag denoting that a class is serializable, such as is needed for I/O.

Cloneable:

        This interface is used to mark how the method clone() should be used to provide a deep copy of objects that themselves contain references to other objects.

Mouse Input:

Mouse Input requires us to implement a Java Interface. To fully understand this we would need to understand Inheritance. We can, however, follow enough of a few examples to be able to copy the needed code to implement mouse input in our own programs, as shown in the following examples:
    • The first example in EchoXY.java shows how to echo the mouse position.
    • Next in MouseButtons.java we see how to detect which "buttons" on the screen have been pressed.
    • Then in SimpleAnimation.java we see how to implement some pseudo-animation, to detect intersection between objects on the screen.

The above projects are part of the UsingMouse BlueJ project that uses Canvas.javaSquare.java, and Circle.java. Of these only the Canvas class has an additional method (to register mouse events with the display frame) from what we've seen before in these classes. Download all of these together in UsingMouse.zip

ĉ
Dale Reed,
Aug 5, 2016, 2:38 PM
Comments