Memra

Abstract classes & methods

◈ 5 cards

Partially-implemented base classes that define a contract subclasses must complete.

A base class that cannot be instantiated

Sometimes a base class exists only to define a common shape for its subclasses — it has no meaningful standalone object. In the Greenhouse control system, every control action (turn the light on, open the water, ring the bell) is an Event, but there is no such thing as a bare "Event" object — the what to do differs for each kind. Java models this with an abstract class.

An abstract class:

  • is declared abstract and cannot be instantiatednew Event(1000) is a compile error;
  • may contain ordinary fields, constructors, and fully-implemented methods (shared behaviour);
  • may contain abstract methods — a method signature with no body, ending in a semicolon, that every concrete subclass is forced to override.

If a class has even one abstract method it MUST be declared abstract. The compiler then guarantees that any concrete (non-abstract) subclass supplies a body for every inherited abstract method, so callers can rely on the method existing.

Worked example — the project's Event

public abstract class Event {
  private long eventTime;
  protected final long delayTime;

  public Event(long delayTime) {
    this.delayTime = delayTime;
    start();
  }
  public void start() {                 // shared, concrete
    eventTime = System.currentTimeMillis() + delayTime;
  }
  public boolean ready() {              // shared, concrete
    return System.currentTimeMillis() >= eventTime;
  }
  public abstract void action();        // abstract — no body
}

Notice the mix: Event carries real state (eventTime, delayTime), a constructor, and two concrete methods (start, ready) that every event shares — but action() is abstract because what the event does is different for each subclass. A subclass becomes concrete only by implementing action():

class Bell extends Event {
  public Bell(long delayTime) { super(delayTime); }
  public void action() { /* ring */ }   // now concrete
}

Because Event has an abstract method, you can declare a variable of type Event and hold any subclass through it (Event e = new Bell(1000);) — but you can never write new Event(...).

implements action()omits action()Eventabstract: new Event(1000) rejectedBellconcrete: new Bell(1000) compilessubclass with no action()still abstract; must say so
Only a subclass that supplies a body for action() becomes concrete. Event itself — and any subclass that still leaves action() unimplemented — must be declared abstract and cannot be instantiated.
NORMAL ~/memra/learn/comp-308/abstract-classes-and-methods utf-8 LF