Interfaces

IB Syllabus: B3.2 (HL) – Use interfaces to define contracts that classes must implement.

HL Only – This page covers content assessed at HL level only.

Table of Contents

  1. Key Concepts
    1. What is an Interface?
    2. Implementing an Interface
    3. Interface as a Type
    4. Multiple Interfaces
    5. Combining Interfaces and Inheritance
    6. Interface vs Abstract Class
  2. Worked Examples
    1. Example 1: Comparable Items
    2. Example 2: Multiple Interfaces
  3. Quick Check
  4. Trace Exercise
  5. Spot the Error
  6. Predict the Output
  7. Practice Exercises
    1. Core
    2. Extension
    3. Challenge
  8. Connections

Key Concepts

What is an Interface?

An interface defines a contract – a set of method signatures that any implementing class must provide. It specifies what a class can do, without specifying how it does it.

public interface Drawable {
    void draw();
    String getDescription();
}

An interface contains only:

  • Abstract method signatures (no method bodies)
  • Constants (public static final by default)

It contains no constructors, no instance variables, and no method implementations.

Implementing an Interface

A class uses the implements keyword to adopt an interface. It must then provide a body for every method declared in the interface:

public class Circle implements Drawable {
    private double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    @Override
    public void draw() {
        System.out.println("Drawing a circle with radius " + radius);
    }

    @Override
    public String getDescription() {
        return "Circle (r=" + radius + ")";
    }
}

public class TextBox implements Drawable {
    private String text;

    public TextBox(String text) {
        this.text = text;
    }

    @Override
    public void draw() {
        System.out.println("Rendering text: " + text);
    }

    @Override
    public String getDescription() {
        return "TextBox: " + text;
    }
}

If a class says implements Drawable but does not provide draw() and getDescription(), the compiler reports an error.

An interface is a promise. When a class implements an interface, it guarantees it will provide all the methods the interface declares. Other code can rely on this guarantee without knowing the specific class.

Interface as a Type

Just like abstract classes, interfaces can be used as variable types, parameter types, and array types:

Drawable[] canvas = new Drawable[3];
canvas[0] = new Circle(5);
canvas[1] = new TextBox("Hello");
canvas[2] = new Circle(3);

for (int i = 0; i < canvas.length; i++) {
    System.out.println(canvas[i].getDescription());
    canvas[i].draw();
}

Output:

Circle (r=5.0)
Drawing a circle with radius 5.0
TextBox: Hello
Rendering text: Hello
Circle (r=3.0)
Drawing a circle with radius 3.0

The loop does not know or care whether each element is a Circle or a TextBox. It only knows each element is Drawable and therefore has draw() and getDescription().

Multiple Interfaces

A class can implement multiple interfaces. This is a key advantage over inheritance, where a class can only extend one parent:

public interface Printable {
    void print();
}

public interface Saveable {
    void save(String filename);
}

public class Document implements Printable, Saveable {
    private String content;

    public Document(String content) {
        this.content = content;
    }

    @Override
    public void print() {
        System.out.println("Printing: " + content);
    }

    @Override
    public void save(String filename) {
        System.out.println("Saving to " + filename);
    }
}

Document implements both Printable and Saveable. It can be stored in a Printable[] array OR a Saveable[] array, depending on context. This flexibility is impossible with single inheritance alone.

Java allows single inheritance (one extends) but multiple interface implementation (many implements). This is how Java provides the benefits of multiple inheritance without the complexity.

Combining Interfaces and Inheritance

A class can extend a parent class AND implement one or more interfaces at the same time:

public abstract class Shape {
    private String colour;

    public Shape(String colour) {
        this.colour = colour;
    }

    public String getColour() { return colour; }
    public abstract double getArea();
}

public class Circle extends Shape implements Drawable {
    private double radius;

    public Circle(String colour, double radius) {
        super(colour);
        this.radius = radius;
    }

    @Override
    public double getArea() {
        return Math.PI * radius * radius;
    }

    @Override
    public void draw() {
        System.out.println("Drawing " + getColour() + " circle");
    }

    @Override
    public String getDescription() {
        return getColour() + " circle (r=" + radius + ")";
    }
}

Circle inherits from Shape (getting colour and requiring getArea()) and implements Drawable (requiring draw() and getDescription()). The extends clause comes before implements.

Interface vs Abstract Class

Feature Abstract Class Interface
Keyword abstract class interface
Adoption extends (one only) implements (many allowed)
Constructors Yes No
Instance variables Yes No (constants only)
Concrete methods Yes (shared behaviour) No (only signatures)
Abstract methods Yes (some or all) All methods are abstract
When to use Classes share common state and behaviour Unrelated classes share a capability

When to use an abstract class:

  • The subclasses share attributes and concrete methods (e.g., Animal with name, age, getName())
  • There is a clear is-a hierarchy

When to use an interface:

  • Multiple unrelated classes need the same capability (e.g., Drawable, Comparable, Serializable)
  • A class needs to conform to multiple contracts

Think of abstract classes as “what something IS” and interfaces as “what something CAN DO.” A Dog IS an Animal (abstract class), but a Dog CAN be Trainable (interface).


Worked Examples

Example 1: Comparable Items

A shop needs to sort products and students by different criteria. Both can be compared, but they are completely unrelated classes.

public interface Sortable {
    int getSortKey();
}

public class Product implements Sortable {
    private String name;
    private double price;

    public Product(String name, double price) {
        this.name = name;
        this.price = price;
    }

    public String getName() { return name; }
    public double getPrice() { return price; }

    @Override
    public int getSortKey() {
        return (int) (price * 100);  // sort by price in cents
    }
}

public class Student implements Sortable {
    private String name;
    private int score;

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

    public String getName() { return name; }
    public int getScore() { return score; }

    @Override
    public int getSortKey() {
        return score;  // sort by score
    }
}

A single sort method works for ANY Sortable array:

// Selection sort that works on ANY Sortable objects
public static void sort(Sortable[] items) {
    for (int i = 0; i < items.length - 1; i++) {
        int minIndex = i;
        for (int j = i + 1; j < items.length; j++) {
            if (items[j].getSortKey() < items[minIndex].getSortKey()) {
                minIndex = j;
            }
        }
        Sortable temp = items[minIndex];
        items[minIndex] = items[i];
        items[i] = temp;
    }
}
Product[] products = {
    new Product("Laptop", 999.99),
    new Product("Mouse", 29.99),
    new Product("Keyboard", 79.99)
};
sort(products);

for (int i = 0; i < products.length; i++) {
    System.out.println(products[i].getName() + ": $" + products[i].getPrice());
}

Output:

Mouse: $29.99
Keyboard: $79.99
Laptop: $999.99

The sort() method does not know about Product or Student. It only relies on the Sortable interface contract.

Example 2: Multiple Interfaces

A smart home system where devices can be both controllable and monitorable.

public interface Controllable {
    void turnOn();
    void turnOff();
    boolean isOn();
}

public interface Monitorable {
    String getStatus();
}

public class SmartLight implements Controllable, Monitorable {
    private String room;
    private boolean on;

    public SmartLight(String room) {
        this.room = room;
        this.on = false;
    }

    @Override
    public void turnOn() { on = true; }

    @Override
    public void turnOff() { on = false; }

    @Override
    public boolean isOn() { return on; }

    @Override
    public String getStatus() {
        return room + " light: " + (on ? "ON" : "OFF");
    }
}

public class Thermostat implements Controllable, Monitorable {
    private double temperature;
    private boolean on;

    public Thermostat(double temperature) {
        this.temperature = temperature;
        this.on = false;
    }

    @Override
    public void turnOn() { on = true; }

    @Override
    public void turnOff() { on = false; }

    @Override
    public boolean isOn() { return on; }

    @Override
    public String getStatus() {
        String state = on ? "heating to " + temperature + "C" : "OFF";
        return "Thermostat: " + state;
    }
}
Controllable[] devices = {
    new SmartLight("Kitchen"),
    new Thermostat(22.0)
};

// Turn everything on
for (int i = 0; i < devices.length; i++) {
    devices[i].turnOn();
}

// Check status (need to cast to Monitorable)
for (int i = 0; i < devices.length; i++) {
    Monitorable m = (Monitorable) devices[i];
    System.out.println(m.getStatus());
}

Output:

Kitchen light: ON
Thermostat: heating to 22.0C

Both SmartLight and Thermostat implement two interfaces. They can be treated as Controllable (to turn on/off) or Monitorable (to check status), depending on what the code needs.


Quick Check

Q1. What does an interface contain?

Q2. How many interfaces can a single class implement?

Q3. A class implements Drawable but does not provide a draw() method. What happens?

Q4. When should you use an interface instead of an abstract class?

Q5. What is the correct syntax for extending a class AND implementing an interface?


Trace Exercise

Trace the interface method calls. SmartLight and Thermostat both implement Controllable and Monitorable.

Trace: Interface Dispatch

SmartLight light = new SmartLight("Living Room");
Thermostat thermo = new Thermostat(21.5);

light.turnOn();
thermo.turnOn();
thermo.turnOff();
DeviceisOn()getStatus()
light
thermo

The thermostat was turned on, then turned off again. Its final state is off.


Spot the Error

This code defines an interface and a class that should implement it. Find the error.

Bug Hunt: A media player interface. The AudioPlayer class should implement all methods from Playable, which declares play(), stop(), and pause().

1public interface Playable { 2 void play(); 3 void stop(); 4 void pause(); 5} 6 7public class AudioPlayer implements Playable { 8 // missing pause() implementation 9 public void play() { System.out.println("Playing"); } 10 public void stop() { System.out.println("Stopped"); } 11}

Pick the correct fix for line 8:


Predict the Output

Using the Drawable interface from Key Concepts, where Circle.getDescription() returns "Circle (r=" + radius + ")" and TextBox.getDescription() returns "TextBox: " + text. What does this print?

Drawable[] canvas = new Drawable[2];
canvas[0] = new Circle(5);
canvas[1] = new TextBox("Hello");
System.out.println(canvas[0].getDescription());
System.out.println(canvas[1].getDescription());

Type both lines separated by \n:


Practice Exercises

Core

  1. Measurable interface – Create an interface Measurable with a method double getMeasurement(). Create two classes: Ruler (returns its length in cm) and Thermometer (returns the current temperature). Store both in a Measurable[] array and print each measurement.

  2. Interface type – Given Drawable[] items = new Drawable[3];, explain why items[0] = new Drawable(); would cause a compile error, but items[0] = new Circle(5); works (assuming Circle implements Drawable).

Extension

  1. Two interfaces – Create interfaces Readable (with String read()) and Writable (with void write(String data)). Create a File class that implements both. Create a Keyboard class that implements only Readable. Demonstrate using the interface types for polymorphic arrays.

  2. Compare and contrast – Rewrite the abstract Shape class from the Abstract Classes page as an interface called ShapeSpec instead. What do you lose? What do you gain? Which approach is better for shapes, and why?

Challenge

  1. Plugin system – Design an interface Plugin with methods String getName(), void execute(), and int getPriority(). Create three concrete plugins: SpellChecker, WordCounter, and AutoSaver. Write a PluginManager class that stores plugins in an array, sorts them by priority (lowest first), and executes them in order.

Connections


© EduCS.me — A resource hub for IB Computer Science

This site uses Just the Docs, a documentation theme for Jekyll.