Using an Abstract Class

Now we look at a better design:

where Roster is an abstract class:

public abstract class Roster {
  protected Student[] students;
  protected int numStudents;

  public Roster(int size) {
    students = new Student[size];
    numStudents = 0;
  }

  public abstract void add(Student s);

  public abstract void remove(Student s);

  public abstract Student find(String email);
}

An abstract class is declared with the abstract keyword. It signals that it cannot be instantiated (even that it has a constructor).

An abstract class typically contains one or more abstract methods.

An abstract method is a method that is declared with abstract keyword and without an implementation.

Instead of curly brackets { }, an abstract method's signature ends with a semicolon.

Any (non-abstract) subclass that extends an abstract class is responsible to implement its abstract methods.

Exercise Why is the design above better than those presented earlier?

Solution
  • It defines semantically sound "is-a" relationships.

  • We can leverage from type substitution. For example, we can have an array of type Roster and store rosters of type JhuRoster and MoocRoster in there.

  • Roster does not implement the core operations; it is the responsibility of its subclasses to do so. These subclasses must adhere to the "interface" (method signatures of core operations) provided by Roster.

  • Roster cannot be instantiated (which gets around the problem of declaring it as a regular class and leaving implementations empty as stubs).

Aside: An example of a (non-abstract) method that can be implemented in the abstract class Roster is

public int getNumStudents() {
  return numStudents;
}

This method can be used by all classes that extend Roster.

Resources