Abstract classes and methods

Bruce Eckel’s Thinking in Java Contents | Prev | Next

and
methods

In
all the instrument examples, the methods in the base class
Instrument
were always “dummy” methods. If these methods are ever called,
you’ve done something wrong. That’s because the intent of
Instrument
is to create a
common
interface

for all the classes derived from it.

If
you have an abstract class like
Instrument,
objects of that class almost always have no meaning. That is,
Instrument
is meant to express only the interface, and not a particular implementation, so
creating an
Instrument
object makes no sense, and you’ll probably want to prevent the user from
doing it. This can be accomplished by making all the methods in
Instrument
print error messages, but this delays the information until run-time and
requires reliable exhaustive testing on the user’s part. It’s
always better to catch problems at compile time.

Java
provides a mechanism for doing this called the
abstract
method
.
This is a method that is incomplete; it has only a declaration and no method
body. Here is the syntax for an abstract method declaration:

abstract
void X();

A
class containing abstract methods is called an
abstract
class
.
If a class contains one or more abstract methods, the class must be qualified as
abstract.
(Otherwise, the compiler gives you an error message.)

If
an abstract class is incomplete, what is the compiler supposed to do when
someone tries to make an object of that class? It cannot safely create an
object of an abstract class, so you get an error message from the compiler.
This way the compiler ensures the purity of the abstract class, and you
don’t need to worry about misusing it.

It’s
possible to declare a class as
abstract
without
including any
abstract
methods. This is useful when you’ve got a class in which it doesn’t
make sense to have any
abstract
methods, and yet you want to prevent any instances of that class.

The
Instrument
class can easily be turned into an abstract class. Only some of the methods
will be abstract, since making a class abstract doesn’t force you to make
all the methods abstract.

Here’s
what it looks like:

//: Music4.java
// Abstract classes and methods
import java.util.*;
 
abstract class Instrument4 {
  int i; // storage allocated for each
  public abstract void play();
  public String what() {
    return "Instrument4";
  }
  public abstract void adjust();
}
 
class Wind4 extends Instrument4 {
  public void play() {
    System.out.println("Wind4.play()");
  }
  public String what() { return "Wind4"; }
  public void adjust() {}
}
 
class Percussion4 extends Instrument4 {
  public void play() {
    System.out.println("Percussion4.play()");
  }
  public String what() { return "Percussion4"; }
  public void adjust() {}
}
 
class Stringed4 extends Instrument4 {
  public void play() {
    System.out.println("Stringed4.play()");
  }
  public String what() { return "Stringed4"; }
  public void adjust() {}
}
 
class Brass4 extends Wind4 {
  public void play() {
    System.out.println("Brass4.play()");
  }
  public void adjust() {
    System.out.println("Brass4.adjust()");
  }
}
 
class Woodwind4 extends Wind4 {
  public void play() {
    System.out.println("Woodwind4.play()");
  }
  public String what() { return "Woodwind4"; }
}
 
public class Music4 {
  // Doesn't care about type, so new types
  // added to the system still work right:
  static void tune(Instrument4 i) {
    // ...
    i.play();
  }
  static void tuneAll(Instrument4[] e) {
    for(int i = 0; i < e.length; i++)
      tune(e[i]);
  }
  public static void main(String[] args) {
    Instrument4[] orchestra = new Instrument4[5];
    int i = 0;
    // Upcasting during addition to the array:
    orchestra[i++] = new Wind4();
    orchestra[i++] = new Percussion4();
    orchestra[i++] = new Stringed4();
    orchestra[i++] = new Brass4();
    orchestra[i++] = new Woodwind4();
    tuneAll(orchestra);
  }
} ///:~ 

You
can see that there’s really no change except in the base class.

It’s
helpful to create
abstract
classes
and methods because they make the abstractness of a class explicit and tell
both the user and the compiler how it was intended to be used.

More by Author

Must Read