Interfaces and Abstract Classes

Interfaces

A method has two parts: operation and implementation. The operation is simply the first line of the method's declaration. For example:

public void deposit(Double amount)

The implementation is the block that follows:

{ this.balance += amount; }

An interface is a named collection of operations.

public interface Playable {
  public void play();
  public void pause();
  public void resume();
  public void stop();
}

Interfaces can extend other interfaces:

public interface Recordable extends Playable {
   // turn recording on/off
   public void record(Boolean flag);
}

A class can implement zero or more interfaces:

class TapePlayer implements Recordable {
   public void play() { ... }
   public void stop() { ... }
   public void pause() { ... }
   public void record(Boolean flag) { ... }
}

Here's the UML notation:

Polymorphism

Here's a fragment of the Studio declaration:

public class Studio {
 
  private Playable player;
 
  public void setPlayer(Playable player) {
     this.player = player;
  }

  // etc.
}

Assume we declare a studio and supply it with a player:

Studio sun = new Studio();
CDPlayer sony = new CDPlayer();
sun.setPlayer(sony);

Notice that the parameter of setPlayer has type Playable, while the argument, sony, has type CDPlayer. In earlier languages this would cause a type mismatch error, but Java's type checker allows an object to have many types. An instance of CDPlayer has type CDPlayer, Object, and Playable. We say that CDPlayers can masquerade as Objects and Playables.

Why not dispense with the charade and simply declare the player to be of type CDPlayer:

public class Studio {
 
  private CDPlayer player;

  // etc.
}

Well?

Abstraction Principle

The Abstraction Principle of Software Engineering states:

An interface should be independent of its implementation

In practice, this means that in order to use a CDPlayer, for example, a client should only need to understand its interface. Imagine if in order to play a CD one needed to know how CD players worked!

Interfaces can be specified in design models to allow clients of a class to begin working on their code before the implementation of the interface is ready. Sometimes mock implementations are provided so that clients can test their code.

Abstract Classes

An interface does not contain variables or methods. They must be declared by implementing classes. This can lead to code replication when a variable or method is common to all implementing classes.

For example, suppose all playables have a state that some of the methods must set:

In each of the three implementing classes we would need to introduce a state variable and code for setting the variable.

Alternatively, we can declare an abstract Player class:

abstract public class Player {
 
  protected PlayerState state = PlayerState.STOPPED;
 
  public void play() { state = PlayerState.PLAYING; }
  public void pause() { state = PlayerState.PAUSED; }
  public void resume() { state = PlayerState.PLAYING; }
  public void stop() { state = PlayerState.STOPPED; }

}

Where:

public enum PlayerState {
  PLAYING,
  PAUSED,
  STOPPED
}

Here's the UML notation:

Implementing classes can redefine the inherited methods and call them:

class DVDPlayer extends Player {
   public void play() {
      super.play(); // change state
      // DVD-specific play code goes here
   }
   // etc.
}

Notes

·      In UML names of abstract classes and methods are italicized.

·      Abstract classes can't be instantiated:

Player p = new Player(); // error
Player p = new CDPlayer(); // ok CDPlayers can masquerade as Players

·      A class is abstract if it contains an abstract method. This can happen if a class declares an abstract method or inherits one and doesn't implement it.

·       We declared state protected so that it could be accessed by subclasses.

·       Unfortunately, a class can implement as many interfaces as it wants, but it can only inherit from one class.