Lesson 9 of 13

Interfaces, Abstract Classes & Generics

describe what a type can do, and let one or work with many types while keeping compile-time checks. Both appear throughout the Java .

Java
// An interface is a contract: methods without bodies (plus default/static ones).
interface Shape {
    double area();                       // every implementer must provide this
    double perimeter();

    default String describe() {          // default method — inherited body
        return String.format("%s: area=%.2f", getClass().getSimpleName(), area());
    }

    static Shape unitSquare() {          // static factory on the interface
        return new Rectangle(1, 1);
    }
}

record Rectangle(double width, double height) implements Shape {
    public double area()      { return width * height; }
    public double perimeter() { return 2 * (width + height); }
}

record Circle(double radius) implements Shape {
    public double area()      { return Math.PI * radius * radius; }
    public double perimeter() { return 2 * Math.PI * radius; }
}

// A class can implement MANY interfaces but extend only ONE class.
public class Demo {
    public static void main(String[] args) {
        List<Shape> shapes = List.of(new Rectangle(3, 4), new Circle(2));
        for (Shape s : shapes) System.out.println(s.describe());
    }
}
Java
// Abstract classes sit between interfaces and concrete classes:
// they hold STATE and constructors, which interfaces cannot.
abstract class Employee {
    protected final String name;
    protected final double baseSalary;

    protected Employee(String name, double baseSalary) {
        this.name = name;
        this.baseSalary = baseSalary;
    }

    public abstract double monthlyPay();      // subclasses must define

    public String payslip() {                 // shared behaviour
        return "%s: %.2f".formatted(name, monthlyPay());
    }
}

class Salaried extends Employee {
    Salaried(String name, double annual) { super(name, annual); }
    public double monthlyPay() { return baseSalary / 12; }
}

class Contractor extends Employee {
    private final int hours;
    Contractor(String name, double rate, int hours) {
        super(name, rate);
        this.hours = hours;
    }
    public double monthlyPay() { return baseSalary * hours; }
}

// Rule of thumb: interface for capability ("Comparable", "Closeable"),
// abstract class when subclasses genuinely share fields and construction logic.
Java
import java.util.*;

// A generic class: T is a placeholder chosen by the caller.
class Box<T> {
    private T value;
    public void put(T value) { this.value = value; }
    public T get()           { return value; }
}

// Bounded type parameter: T must be Comparable with itself.
class Range<T extends Comparable<T>> {
    private final T low, high;
    Range(T low, T high) { this.low = low; this.high = high; }
    boolean contains(T v) { return low.compareTo(v) <= 0 && high.compareTo(v) >= 0; }
}

public class Generics {
    // Generic method — <T> declared before the return type
    static <T> List<T> repeat(T item, int times) {
        List<T> out = new ArrayList<>();
        for (int i = 0; i < times; i++) out.add(item);
        return out;
    }

    // Wildcards control what you can read and write:
    //   ? extends Number  -> you can READ Numbers  (producer)
    //   ? super Integer   -> you can WRITE Integers (consumer)
    static double sum(List<? extends Number> nums) {
        double total = 0;
        for (Number n : nums) total += n.doubleValue();
        return total;
    }

    static void addInts(List<? super Integer> sink) {
        sink.add(1);
        sink.add(2);
    }

    public static void main(String[] args) {
        Box<String> box = new Box<>();
        box.put("hello");
        System.out.println(box.get().length());     // no cast needed

        System.out.println(new Range<>(1, 10).contains(7));   // true
        System.out.println(sum(List.of(1, 2.5, 3L)));         // 6.5
        System.out.println(repeat("x", 3));                   // [x, x, x]
    }
}
Finished reading?Mark it done to track your progress.

Tip: use the ← and → keys to move between lessons.