Lecture 14

Agenda

Announcements

Interfaces

Our main topic today is a Java feature called "Interfaces". This topic is closely related to our discussion of object-oriented design from the preceding lectures. It is also, unfortunately, tangentially related to the topic of the next few classes, Java User interface mechanisms. That is, while this topic "Interfaces" and the next topic "User Interfaces" share part of their name, the connection between the two topics is not very strong.

As we hinted, however, there is a strong connecting between Interfaces and object-oriented design.

In our discussion of design, we saw that an important goal was to hide the details of how the behavior of a class was implemented by keeping its instance variables private and then defining public methods that provided the ability to change or determine a limited set of aspects of the object's state.

The collection of operations/methods that can be used from outside a class to interact with an object of the class is called the interface to the class. This explains why the topics "Interfaces" and "User Interfaces" have related names. "User Interfaces" are the mechanisms through which users can interact with the state of an entire program. "Interfaces" are the mechanisms through which one component (object) within a program can interact with another.

The interface of objects of a Java class can be concisely described by listing all of its methods and describing their parameters. That is why we ask you to include such informations in your designs.

Your designs are (quite deliberately) not actual Java code. It turns out, however, to be quite useful to write a description of a classes interface in a form that is interpretable as Java code by the computer. Accordingly, Java's rules of syntax permit such a specification.

To illustrate the use of this new Java mechanism we will use the Tshirt class from our laundry sorter as an example.

The form of an interface specification is quite simple:

public interface Laundry {

...

}

For example, here is an interface specification for the properties of the Tshirts used in our laundry sorter program.

// A piece of laundry of an arbitrary shape.
public interface Laundry {

      // Move the laundry relative to its current position
      // Parameter:
      //    xOffset - distance to move horizontally
      //    yOffset - distance to move vertically
      public void move( double xOffset, double yOffset );

      // Move the laundry to a specific position:
      //    x - x coordinate
      //    y - y coordinate
      public void moveTo( double x, double y );

      // Remove the laundry from the display
      public void hide ();

      // Return true if the point is in the laundry
      // Parameters:
      //    pt - the point to test for containment
      public boolean contains( Location pt);

      // Return the sum of the redness, blueness,
      // and greenness of the laundry item.
      public int colorValue(  );
}

With this interface included in our program, we can now construct a more advanced version of the laundry sorter.

We hope that you noticed that, thanks to the use of a class definition, we had to change very little when we converted our initial laundry program (where the laundry items were just FilledRects) into our current, fancy Tshirt version. Basically, the only change required was that the declaration:

FilledRect item;

had to be replaced by a declaration of the form:

Tshirt item;

and to change the constructor used.

The code that manipulated the laundry (i.e. onMouseDrag, etc.) remained unchanged. We didn't have a precise way of explaining why at the time, but now we do. FilledRects and Tshirts provide a similar interface. That is, they both provide all the methods we need for this program (including, move, moveTo, contains, etc.)

Interfaces let us write even more flexible code.

Suppose we have two classes of laundry defined. Tshirts (as before) and something else like Pants. If they both contains all the methods listed in our Laundry interface, we can explicitly tell Java this in the headers of the class declarations:

      public class Tshirt implements Laundry ...

So long as we restrict ourselves to the methods defined by the Laundry interface, it doesn't matter what type of laundry we come up with in the future (maybe we want to add Shorts when it gets warmer), we can continue to use any program that uses the Laundry interface without changing it!

To tell Java that we want to use objects that implement the Laundry interface in our laundry sorter, we can replace the declaration of the item variable in the window controller with a declaration of the form:

Laundry item;

When we write a declaration, remember that we are telling Java what sort of object the name may be associated with. The declaration "Laundry item" tells Java that item may be associated with an object of any class that implements the Laundry interface.

So, Java will allows us to say either:

item = new Tshirt( ... );

or

item = new Pants( ... );

On the other hand, java will not allow us to say:

item = new Laundry( ... );

This makes a lot of sense. In the specification of the interface Laundry, we did not include a constructor. That is because in order to construct an object, we need to know the details of how its state will be represented. The whole point of an interface, however, is to focus on the interface through which the state can be manipulated while ignoring the details of how the state is represented.

On the other hand, given that Java knows that "item" will only be associated with things that implement the Laundry interface, it will let us write commands like:

      item.moveTo(...);

Note that Java will not allow us to assign any object with the right methods to the "item" variable. In particular, even if the methods in the Laundry interface were a subset of those provided by FilledRects, we could not say:

      item = new FilledRect( ... );

since the declaration of the class FilledRect does not say:

      public class FilledRect implements Laundry {

      }

Demo: Laundry Sorter using interfaces

Also, note that we can use interface names as type names in parameter declarations.

Interface Example Two - Boxball

The Boxball class as a Ball-user must provide an onMouseHittingBottom method since Ball objects will call this method when they reach the bottom of the playing area. We could create a BallUser interface to force the Boxball to provide the necessary onMouseHittingBottom method as:


public interface BallUser { 
    public void onBallHittingBottom(double x); 
} // end BallUser

The Boxball class declaration would become:

public class Boxball extends WindowController implements BallUser {

 

The Ball class should be modified by replacing the Boxball references by BallUser interface. The Java compiler will issue an error message if Boxball tries to use a Ball without implementing the BallUser interface. Plus, the Java compiler will issue an error message if Boxball does implement BallUser interface without supplying an onMouseHittingBottom method with a double parameter.

The AWT components (Button, Choice drop-down menu, Scrollbar, etc.) that we will be using are very similar to Boxball. In order to use an AWT component we will need to implement the appropriate interface, i.e., we will be forced to provide appropriate methods that will be called to response to an action on the AWT component (such as a Button press).