The `extends` keyword

java
public class Vehicle {
    private String make;
    private int year;
    
    public Vehicle(String make, int year) {
        this.make = make;
        this.year = year;
    }
    
    public String getMake() { return make; }
    public int getYear() { return year; }
    
    public String describe() {
        return year + " " + make;
    }
}

public class Car extends Vehicle {
    private int numDoors;
    
    public Car(String make, int year, int numDoors) {
        super(make, year);  // MUST call superclass constructor
        this.numDoors = numDoors;
    }
    
    public int getNumDoors() { return numDoors; }
}
java
Car myCar = new Car("Toyota", 2024, 4);
System.out.println(myCar.describe());      // "2024 Toyota" (inherited)
System.out.println(myCar.getNumDoors());   // 4 (own method)

What gets inherited?

java
public class Car extends Vehicle {
    public void printInfo() {
        // System.out.println(make);    // COMPILE ERROR — make is private
        System.out.println(getMake());  // OK — using inherited getter
    }
}

The `super()` constructor call

java
public class Car extends Vehicle {
    private int numDoors;
    
    public Car(String make, int year, int numDoors) {
        super(make, year);       // MUST be first line
        this.numDoors = numDoors;
    }
}
java
public class Car extends Vehicle {
    public Car() {
        // Java inserts: super();  ← looks for Vehicle()
        // If Vehicle has no no-arg constructor → COMPILE ERROR!
    }
}

Constructor rule summary

The "is-a" relationship

java
// Good — makes sense
class Dog extends Animal { }      // a Dog IS an Animal ✓
class Circle extends Shape { }    // a Circle IS a Shape ✓

// Bad — doesn't make sense
class Dog extends Collar { }      // a Dog IS a Collar? ✗
// Use composition instead: Dog HAS a Collar

Adding subclass-specific behavior

java
public class Animal {
    private String name;
    
    public Animal(String name) {
        this.name = name;
    }
    
    public String getName() { return name; }
    
    public String speak() {
        return name + " makes a sound";
    }
}

public class Dog extends Animal {
    private String breed;
    
    public Dog(String name, String breed) {
        super(name);
        this.breed = breed;
    }
    
    public String getBreed() { return breed; }
    
    public String fetch() {
        return getName() + " fetches the ball!";
    }
}
java
Dog rex = new Dog("Rex", "Lab");
System.out.println(rex.speak());     // inherited from Animal
System.out.println(rex.fetch());     // Dog-specific method
System.out.println(rex.getBreed()); // Dog-specific method

Animal a = new Dog("Spot", "Beagle");
// a.fetch();  // COMPILE ERROR — Animal doesn't know about fetch()
a.speak();     // OK — Animal has speak()

Multi-level inheritance

java
class Animal { }
class Dog extends Animal { }
class GuideDog extends GuideDog { }

The Object class

java
class Animal { }  // secretly: class Animal extends Object

Complete example: Employee hierarchy

java
public class Employee {
    private String name;
    private double salary;
    
    public Employee(String name, double salary) {
        this.name = name;
        this.salary = salary;
    }
    
    public String getName() { return name; }
    public double getSalary() { return salary; }
    
    public double annualPay() {
        return salary * 12;
    }
    
    public String toString() {
        return name + " ($" + salary + "/month)";
    }
}

public class Manager extends Employee {
    private double bonus;
    
    public Manager(String name, double salary, double bonus) {
        super(name, salary);
        this.bonus = bonus;
    }
    
    public double getBonus() { return bonus; }
    
    public double annualPay() {
        return super.annualPay() + bonus;
    }
    
    public String toString() {
        return super.toString() + " + $" + bonus + " bonus";
    }
}
java
Employee emp = new Employee("Alice", 5000);
Manager mgr = new Manager("Bob", 7000, 10000);

System.out.println(emp);  // Alice ($5000.0/month)
System.out.println(mgr);  // Bob ($7000.0/month) + $10000.0 bonus

System.out.println(emp.annualPay());  // 60000.0
System.out.println(mgr.annualPay());  // 94000.0

AP Exam Tips

Common Mistakes

Key Vocabulary