CodeMIRAI
0 XP

Abstract classes and interfaces

2 min read 4 runnable examples Quiz included

Abstract classes

An abstract class is an unfinished blueprint. It can't be instantiated, and it can declare abstract methods with no body, which every subclass must implement:

Java
abstract class Shape {
    abstract double area();                 // no body: each shape must supply one

    void describe() {                       // an ordinary method, shared by all shapes
        System.out.printf("%s with area %.2f%n", getClass().getSimpleName(), area());
    }
}

class Circle extends Shape {
    double r;
    Circle(double r) { this.r = r; }
    @Override double area() { return Math.PI * r * r; }
}

class Triangle extends Shape {
    double base, height;
    Triangle(double base, double height) { this.base = base; this.height = height; }
    @Override double area() { return 0.5 * base * height; }
}

public class Main {
    public static void main(String[] args) {
        Shape[] shapes = { new Circle(2), new Triangle(6, 4) };
        for (Shape s : shapes) s.describe();
        // new Shape();    // error: Shape is abstract
    }
}

This fixes a weakness in the last lesson's Shape, whose area() returned a meaningless 0. Now a subclass that forgets to write area() doesn't compile.

Interfaces

An interface is a pure contract: a list of methods that a class promises to provide.

Java
interface Payable {
    double amountDue();
}

interface Printable {
    void print();
}

class Invoice implements Payable, Printable {
    String client;
    double amount;

    Invoice(String client, double amount) {
        this.client = client;
        this.amount = amount;
    }

    public double amountDue() { return amount; }

    public void print() { System.out.println("Invoice for " + client + ": " + amount); }
}

class Salary implements Payable {
    String employee;
    double monthly;

    Salary(String employee, double monthly) {
        this.employee = employee;
        this.monthly = monthly;
    }

    public double amountDue() { return monthly; }
}

public class Main {
    public static void main(String[] args) {
        Payable[] bills = { new Invoice("Acme", 1500), new Salary("Asha", 4200) };
        double total = 0;
        for (Payable p : bills) total += p.amountDue();
        System.out.println("Total due: " + total);
        new Invoice("Globex", 900).print();
    }
}
  • A class implements an interface and must provide all its methods, as public methods.
  • A class can implement many interfaces, but extend only one class.
  • Unrelated classes, like an invoice and a salary, can share an interface, so other code can treat them alike.

Default methods

Java
interface Greeter {
    String name();

    default String greet() {
        return "Hello, " + name() + "!";
    }
}

class Friendly implements Greeter {
    public String name() { return "Asha"; }
}

class Formal implements Greeter {
    public String name() { return "Dr. Rao"; }

    @Override
    public String greet() { return "Good evening, " + name() + "."; }
}

public class Main {
    public static void main(String[] args) {
        System.out.println(new Friendly().greet());
        System.out.println(new Formal().greet());
    }
}

A default method has a body that implementing classes inherit, and may override. It lets an interface gain new methods without breaking every class that already implements it.

Comparable: sorting your own objects

The Java library is built on interfaces. Implement Comparable, and Arrays.sort knows how to order your objects:

Java
import java.util.Arrays;

class Student implements Comparable<Student> {
    String name;
    int score;

    Student(String name, int score) {
        this.name = name;
        this.score = score;
    }

    @Override
    public int compareTo(Student other) {
        return Integer.compare(other.score, score);    // higher scores first
    }

    @Override
    public String toString() { return name + " " + score; }
}

public class Main {
    public static void main(String[] args) {
        Student[] students = { new Student("Leo", 78), new Student("Asha", 92), new Student("Mei", 85) };
        Arrays.sort(students);
        System.out.println(Arrays.toString(students));
    }
}

compareTo returns a negative number if this object comes first, a positive one if the other does, and zero if they're equal.

Abstract class or interface?

Abstract classInterface
fieldsany kindconstants only
constructorsyesno
a class can useonly oneany number
best forsharing code and state among closely related classesa capability that unrelated classes can share

When in doubt, start with an interface.

Finished this lesson?Mark it complete to earn +20 XP and move your progress on.