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
- •
- •
- •
- •
- •
- •