Interfaces are kind of like Boy Scout or Girl Scout merit badges. When a scout has learned to build a bird house, he can walk around wearing a little patch with a picture of one on his sleeve. This says to the world, "I know how to build a bird house." Similarly, an interface is a list of methods that define some set of behavior for an object. Any class that implements each of the methods listed in the interface can declare that it implements the interface and wear, as its merit badge, an extra type--the interface's type.
Interface types act like class types. You can declare variables to be of an interface type, you can declare arguments of methods to accept interface types, and you can even specify that the return type of a method is an interface type. In each of these cases, what is meant is that any object that implements the interface (i.e., wears the right merit badge) can fill that spot. In this sense, interfaces are orthogonal to the class hierarchy. They cut across the boundaries of what kind of object an item is and deal with it only in terms of what it can do. A class implements as many interfaces as it desires. In this way, interfaces in Java replace the need for multiple inheritance (and all of its messy side effects).
An interface looks like a purely abstract class
(i.e., a class with only abstract methods). You
define an interface with the interface keyword
and list its methods with no bodies:
interface Driveable {
boolean startEngine();
void stopEngine();
float accelerate( float acc );
boolean turn( Direction dir );
} The example above defines an interface called
Driveable with four methods. It's acceptable, but
not necessary, to declare the methods in an interface with the
abstract modifier; we haven't done that here.
More importantly, the methods of an interface are always considered public,
and you can optionally declare them as so. Why public? Well, the user of
the interface wouldn't necessarily be able to see them otherwise.
Interfaces define capabilities, so it's common to name
interfaces after their capabilities.
Driveable,
Runnable, and
Updateable are good interface names.
Any class that implements all the methods can then declare it implements
the interface by using a special implements clause
in its class definition:
class Automobile implements Driveable {
...
public boolean startEngine() {
if ( notTooCold )
engineRunning = true;
...
}
public void stopEngine() {
engineRunning = false;
}
public float accelerate( float acc ) {
...
}
public boolean turn( Direction dir ) {
...
}
...
} The class Automobile implements the methods of the
Driveable interface and declares itself
Driveable using an implements
clause.
As shown in Figure 6.5, another class,
such as LawnMower, can also implement the
Driveable interface. The figure illustrates the
Driveable interface being implemented by two
different classes. While it's possible that both
Automobile and Lawnmower could
derive from some primitive kind of vehicle, they don't have to
in this scenario. This is a significant advantage of interfaces over
standard multiple inheritance as implemented in C++.

After declaring the interface, we have a new type,
Driveable. We can declare variables of type
Driveable and assign them any instance of a
Driveable object:
Automobile auto = new Automobile(); Lawnmower mower = new Lawnmower(); Driveable vehicle; vehicle = auto; vehicle.startEngine(); vehicle.stopEngine(); ... vehicle = mower; vehicle.startEngine(); vehicle.stopEngine();
Both Automobile and Lawnmower
implement Driveable and can be considered of
that type.
Interfaces can be used to implement callbacks in Java. A callback is a situation where you'd like to pass a reference to some behavior and have another object invoke it later. In C or C++, this is prime territory for function pointers; in Java, we'll use interfaces instead.
Consider two classes: a TickerTape class that
displays data and a TextSource class that provides
an information feed. We'd like our TextSource
to send any new text data. We could have TextSource
store a reference to a TickerTape object, but
then we could never use our TextSource to send
data to any other kind of object. Instead, we'd have to proliferate
subclasses of TextSource that dealt with different
types. A more elegant solution is to have TextSource
store a reference to an interface type, TextUpdateable:
interface TextUpdateable {
receiveText( String text );
}
class TickerTape implements TextUpdateable {
TextSource source;
init() {
source = new TextSource( this );
...
}
public receiveText( String text ) {
scrollText( text ):
}
...
}
class TextSource {
TextUpdateable receiver;
TextSource( TextUpdateable r ) {
receiver = r;
}
private sendText( String s ) {
receiver.receiveText( s );
}
...
} The only thing TextSource really cares about
is finding the right method to invoke to send text. Thus, we can list that
method in an interface called TextUpdateable
and have our TickerTape implement the interface.
A TickerTape object can then be used anywhere we need something of the type TextUpdateable.
In this case, the TextSource constructor takes
a TextUpdateable object and stores the reference
in an instance variable of type TextUpdateable.
Our TickerTape object simply passes a reference
to itself as the callback for text updates, and the source can invoke its
receiveText() method as necessary.
Although interfaces allow us to specify behavior without implementation, there's one exception. An interface can contain constant variable identifiers; these identifiers appear in any class that implements the interface. This feature allows predefined parameters that can be used with the methods:
interface Scaleable {
static final int BIG = 0, MEDIUM = 1, SMALL = 2;
void setScale( int size );
} The Scaleable interface defines three integers:
BIG, MEDIUM,
and SMALL.
All variables defined in interfaces are implicitly
final
and static; we don't have to use the
modifiers but, for clarity, we recommend you do.
A class that implements Scaleable sees these
variables:
class Box implements Scaleable {
void setScale( int size ) {
switch( size ) {
case BIG:
...
case MEDIUM:
...
case SMALL:
...
}
}
...
} Sometimes, interfaces are created just to hold constants; anyone who implements the interfaces can see the constant names, much as if they were included by a C/C++ include file. This is a somewhat degenerate, but acceptable, use of interfaces.
Sometimes completely empty interfaces serve as a marker
that a class has some special property. The java.io.Serializeable interface
is a good example. Classes that implement Serializable don't
add any methods or variables. Their additional type simply identifies them
to Java as classes that want to be able to be serialized.
An interface can extend another interface, just as a class can extend another class. Such an interface is called a subinterface:
interface DynamicallyScaleable extends Scaleable {
void changeScale( int size );
} The interface DynamicallyScaleable extends our
previous Scaleable interface and adds an additional
method. A class that implements DynamicallyScaleable
must implement all methods of both interfaces.
Interfaces can't specify that they implement other interfaces because
interfaces never include any method implementations. However,
interfaces
are allowed to extend other interfaces. In fact, an interface is
allowed to extend as many interfaces as it wants (multiple inheritance
of interface)--unlike classes, which can only extend a single class.
If you want to extend two or
more interfaces, list them after the
extends keyword, separated by commas:
interface DynamicallyScaleable extends Scaleable, SomethingElseable {
...