Command Palette

Search for a command to run...

PHASE 5Intermediate ~29 min· topic 6 of 13

Topic 5.6

Abstract Classes

In one line

An abstract class is a partly finished class: it can hold fields, constructors and working methods, plus abstract methods with no body that every concrete subclass must fill in. You can't create an object of an abstract class directly.

Think of it like this

A fill-in-the-blanks form. The bank's account-opening form already has the bank's name, the rules and the signature line printed. It leaves blanks for 'Name' and 'Address' that each customer must fill in. You can't open an account with the blank form itself; you need a filled-in copy. The printed parts are the concrete methods; the blanks are the abstract methods.

Words you'll meet

New words in this topic, in plain English. Come back here whenever one feels fuzzy.

Abstract class
A class marked abstract. It can't be instantiated with new and may contain abstract methods.
Abstract method
A method declared with abstract and no body, ending in a semicolon. Subclasses must supply the body.
Concrete class
A normal, non-abstract class. You can create objects from it, and it has a body for every method.
Instantiate
Create an object of a class with new.
Template Method
A design pattern: a parent method fixes the order of steps and lets subclasses fill in some steps.
Hook method
A step in a template method that subclasses can override. It may be abstract (must fill in) or have a default body (may fill in).

Step by step

01Declaring an abstract class

Put abstract before class. Inside, declare abstract methods with abstract and a semicolon instead of a body. Concrete methods in the same class can call the abstract ones, because at run time this will always be some concrete subclass that has a body for them.

describe() below works for every shape without knowing any shape's formula: area() and perimeter() are dispatched dynamically to the real subclass (Topic 5.4).

Main.javawhole filejava
abstract class Shape {
    private final String name;

    protected Shape(String name) { this.name = name; }   // yes, abstract classes have constructors

    abstract double area();          // no body: subclasses decide
    abstract double perimeter();

    String describe() {              // concrete: uses the abstract methods
        return name + ": area=" + area() + " perimeter=" + perimeter();
    }
}

02Why can't I call new Shape()?

If you could, new Shape("blob").area() would have no code to run. Rather than fail at run time, Java forbids it at compile time. At the bytecode level the class carries the ACC_ABSTRACT flag, and the JVM itself throws InstantiationError if anything (such as hand-written bytecode) tries new on it.

But abstract classes *do* have constructors. They run as part of building a subclass object, via super(...), exactly like Topic 5.1. Making the constructor protected documents that it exists only for subclasses.

terminal
$ javac Main.java
── expected output ──
Main.java:2: error: Shape is abstract; cannot be instantiated
public class Main { public static void main(String[] a) { Shape s = new Shape(); } }
^
1 error

03The subclass must finish the job

A concrete subclass must override every abstract method it inherits, from any ancestor. Miss one and the compiler names the first missing method.

An intermediate class can stay abstract: abstract class Car extends Vehicle might implement wheels() but leave fuel() open. Only the last, concrete classes (PetrolCar, ElectricCar) must have everything.

The subclass must finish the jobdiagram
Rendering diagram…

04Template Method: the parent controls the flow

An exporter always does the same steps: header, every row, footer. Only the *format* of each step changes between CSV and JSON. Put the fixed sequence in a final method in the abstract parent; declare the varying steps abstract (must override) or give them an empty default body (may override, called hooks).

Making the template method final stops subclasses from reordering or skipping steps. This is the Template Method pattern; the System Design course covers it in depth at /topic/phase-2/template-method. The JDK uses it widely: java.io.InputStream.read(byte[], int, int) is built on the abstract single-byte read(), and AbstractList builds iteration on your get and size.

Template Method: the parent controls the flowdiagram
Rendering diagram…

05Abstract classes in the JDK

You use abstract classes every day: java.util.AbstractList, AbstractMap, java.io.InputStream, java.io.Reader, java.lang.Number (the parent of Integer, Double, BigDecimal, with abstract intValue(), doubleValue(), and so on).

Number shows the idea perfectly: every number can give you an int or a double, but each kind does it differently, and there is no such thing as a plain 'Number' object.

Try it yourself

  1. 1

    Add a Triangle

    In the Shape example, add Triangle(double a, double b, double c). Use Heron's formula for the area: s = (a+b+c)/2, area = Math.sqrt(s*(s-a)*(s-b)*(s-c)). For 3, 4, 5, predict area=6.00 perimeter=12.00, then run.

  2. 2

    Forget a method on purpose

    Delete perimeter() from Rectangle and compile. Read which method the compiler says is missing. Then mark Rectangle abstract instead and see the error move to new Rectangle(2, 3).

  3. 3

    Try to override the template

    In the exporter example, add public void export(List<String> rows) { } to TextExporter. The compiler stops you because export is final. That protection is the point of the pattern.

Code & diagrams

An abstract Shape with two concrete shapes New tab
Sign in to run this example in your browser.

Expected output

Shape constructor for circle
Shape constructor for rectangle
circle: area=3.14 perimeter=6.28
rectangle: area=6.00 perimeter=10.00
Template Method with abstract steps and hooks New tab
Sign in to run this example in your browser.

Expected output

== CSV export ==
name,score
Asha,90
Ravi,85
(2 rows)
== TEXT export ==
Asha scored 90
Ravi scored 85
(2 rows)
Abstract in the middle of a hierarchy New tab
Sign in to run this example in your browser.

Expected output

PetrolCar: 4 wheels, runs on petrol
ElectricCar: 4 wheels, runs on electricity
Car abstract? true
PetrolCar abstract? false

Break it on purpose

Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.

Break #1

Instantiate an abstract class

Write new Shape() where Shape is abstract.

Main.javawhole filejava
abstract class Shape { abstract double area(); }
public class Main { public static void main(String[] a) { Shape s = new Shape(); } }
terminal
$ javac Main.java
── what you'll see ──
Main.java:2: error: Shape is abstract; cannot be instantiated
public class Main { public static void main(String[] a) { Shape s = new Shape(); } }
^
1 error

Break #2

Leave an abstract method unimplemented

Extend Shape without overriding area().

Main.javawhole filejava
abstract class Shape { abstract double area(); }
class Circle extends Shape { }
terminal
$ javac Main.java
── what you'll see ──
Main.java:2: error: Circle is not abstract and does not override abstract method area() in Shape
class Circle extends Shape { }
^
1 error

Break #3

Combine abstract with final

Declare abstract final class Shape.

Main.javawhole filejava
abstract final class Shape { }
terminal
$ javac Main.java
── what you'll see ──
Main.java:1: error: illegal combination of modifiers: abstract and final
abstract final class Shape { }
^
1 error

Myth vs fact

Myth

Abstract classes can't have constructors.

Fact

They can and often do. The constructor runs when a subclass object is created, through super(...).

Myth

An abstract class must have at least one abstract method.

Fact

It needn't. A class with no abstract methods can still be declared abstract just to prevent direct instantiation (for example, a base class only meant for extension).

Myth

Since Java 8 interfaces have default methods, abstract classes are obsolete.

Fact

Interfaces still can't hold instance state, constructors, or non-public instance methods other than private helpers. Abstract classes remain the right tool for shared state plus a template (Topic 5.9).

Pro corner

Extra depth for experienced readers. New to this? Skip it for now and come back later.

  • ▸

    Bytecode: an abstract class has ACC_ABSTRACT in its access flags; abstract methods have ACC_ABSTRACT and no Code attribute. A call to an abstract method is a normal invokevirtual, dispatched through the vtable slot that the concrete subclass fills in.

  • ▸

    If a class is compiled against an older version of an abstract parent and the parent later gains a new abstract method, calling it on the old subclass throws AbstractMethodError at run time (no recompilation means no compile error). That's binary incompatibility, and it's exactly what default methods in interfaces were designed to avoid (Topic 5.8).

  • ▸

    Effective Java's advice, 'design and document for inheritance or else prohibit it', applies doubly to abstract classes: document which hooks are called, in what order, and from which methods (@implSpec in Javadoc). The JDK's AbstractCollection.addAll documents that it calls add for each element, which is precisely what makes the composition example in Topic 5.12 behave the way it does.

Remember this

  1. 1

    Mark a class abstract when it represents a general idea that should never exist on its own. A Shape is always some particular shape; a plain new Shape() makes no sense. The compiler then refuses new Shape() with Shape is abstract; cannot be instantiated.

  2. 2

    An abstract method has a signature and no body: abstract double area();. It says 'every concrete shape can compute its area, but I can't say how'. A class with even one abstract method must itself be declared abstract.

  3. 3

    A concrete subclass (one that is not abstract) must override every inherited abstract method, or the compiler says Circle is not abstract and does not override abstract method area() in Shape. A subclass may also stay abstract and leave some methods for its own children.

  4. 4

    Abstract classes are full classes in every other way: they have fields (state), constructors (called via super(...) from subclasses), concrete methods, static members, and any access modifiers. That is the main difference from interfaces (Topic 5.9).

  5. 5

    The most common use is the Template Method pattern: a concrete (often final) method defines the fixed steps of an algorithm and calls abstract 'hook' methods for the steps that vary. The parent controls the flow; the children supply the details.

  6. 6

    Illegal combinations: abstract final (can't be both unfinishable and unextendable), abstract private (a private method can't be overridden, so could never get a body), and abstract static (static methods aren't overridden).

Explain it without notes

01

What's an abstract class and why can't you instantiate it?

02

Can an abstract class have a constructor? When does it run?

03

Explain the Template Method pattern and why the template method is usually final.

04

Which modifier combinations with abstract are illegal, and why?

Practice

01

Create an abstract Employee with name, an abstract double monthlyPay(), and a concrete payslip() returning "<name>: <pay>". Add SalariedEmployee (annual / 12) and HourlyEmployee (rate × hours).

02

Write an abstract Game with a final play() that calls start(), then takeTurn() three times, then end(). Implement Chess with its own messages.

03

Make an abstract Animal with an abstract sound() and a concrete speak() that prints "<class name> says <sound>". Create Dog and Cow and call speak() on both through an Animal[].

Trade-offs

  • ↔

    An abstract class can share state and code, but a subclass spends its single extends on it. If a type might need another parent, start with an interface and offer an abstract class as an optional helper (the skeletal implementation idiom, Topic 5.9).

  • ↔

    Template methods give the parent tight control of the flow, which also means subclasses depend on the exact call order. Changing the order later is a breaking change for every subclass.

Done when you can

  • Done when you can declare an abstract class with abstract and concrete methods and a constructor.

  • Done when you can explain why new is forbidden and how the constructor still runs.

  • Done when you can implement the Template Method pattern with a final template and hooks.

  • Done when you can name JDK abstract classes like Number, InputStream and AbstractList.

  • Done when you know the illegal modifier combinations with abstract.