Abstract classes & methods
◈ 5 cardsPartially-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
abstractand cannot be instantiated —new Event(1000)is a compile error; - may contain ordinary fields, constructors, and fully-implemented methods (shared behaviour);
- may contain
abstractmethods — 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(...).