Programming Fundamentals for CIS Majors 1
Fall, 2010

CIS 3022
Supplement

 

Working with interfaces

Consider the following code:

interface Example
{
  public void operationA();
  public int operationB();
  public String operationC();
}

The interface is a contract: anything that wants to say is of type Example must implement all three operations.

abstract class AbstractExample implements Example
{
  public void operationA()
  {
    System.out.println( "This operation has been implemented" );
  }

  abstract public int operationB();     // must be declared abstract since
  abstract public String operationC();  // they have not been implemented

  public String toString()  // overrides class Object's toString() 
  {
    return "This is some kind of Example";
  }
}

Because this class did not provide implementations for all the interface Example operations, it had to declare the ones it did not support abstract. Because it contains at least one operation declared abstract, the whole class must also be declared abstract.

class ConcreteExample extends AbstractExample
{
  public int operationB()
  {
    return 11;
  }
}

ConcreteExample inherits the definitions of the operations operationA() and toString() from AbstractExample. It also inherits the interface Example from AbstractExample. If you try to compile ConcreteExample, you'll get an error message:

ConcreteExample is not abstract and does not override abstract method operationC() in AbstractExample

(that is the actual Java compiler's message—BlueJ's error message may be different). The reason for the error is that a concrete class (that is, any non-abstract class) must define (provide an implementation for) all methods declared in class AbstractExample (and by extension, interface Example).

So what if you want to test your implementation of a concrete class before you have implemented all the required methods? Could we declare those missing operations abstract to make the compiler happy? Yes... but... then we'd have to declare the class abstract... and we wouldn't be able to instantiate it to test it. We're right back where we started.

The solution is to use stubs—a stub is a method that does nothing (except return 0 or null, if a return value is required). This makes the compiler happy because it sees that the method has been defined (it doesn't care that the method doesn't do anything). Whenever you write a stub, always write a very obvious comment identifying that it is a stub.

class ConcreteExample extends AbstractExample
{
  public int operationB()
  {
    return 11;
  }

  public String operationC()
  {
    // #### THIS IS A STUB!  DON'T FORGET TO
    // #### WRITE THE REAL IMPLEMENTATION!!

    return null;
  }
}

With this (still unfinished) ConcreteExample, we can now test operationA(), operationB(), and toString().

This website is an original work, Copyright © 2010 by Dave Small. All rights reserved.