Inheritance
IB Syllabus: B3.2 (HL) – Implement inheritance using extends and super.
HL Only – This page covers content assessed at HL level only.
Table of Contents
- Key Concepts
- Worked Examples
- Quick Check
- Trace Exercise
- Spot the Error
- Predict the Output
- Practice Exercises
- Connections
Key Concepts
What is Inheritance?
Inheritance allows a new class (the child or subclass) to reuse and extend the attributes and methods of an existing class (the parent or superclass). The child class inherits everything from the parent and can add new attributes, new methods, or change existing behaviour.
This is an “is-a” relationship: a Dog IS-A Animal, a SavingsAccount IS-A BankAccount, a Hare IS-A Racer.
// Parent class
public class Animal {
private String name;
private int age;
public Animal(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() { return name; }
public int getAge() { return age; }
public String speak() {
return "...";
}
}
// Child class -- inherits name, age, getName(), getAge(), speak()
public class Dog extends Animal {
private String breed;
public Dog(String name, int age, String breed) {
super(name, age); // call the parent constructor
this.breed = breed;
}
public String getBreed() { return breed; }
// Override the parent's speak() method
@Override
public String speak() {
return "Woof!";
}
}
Dog d = new Dog("Max", 3, "Labrador");
System.out.println(d.getName()); // Max -- inherited from Animal
System.out.println(d.getAge()); // 3 -- inherited from Animal
System.out.println(d.getBreed()); // Labrador -- defined in Dog
System.out.println(d.speak()); // Woof! -- overridden in Dog
The Dog class did not define getName() or getAge() – it inherited them from Animal. It added breed and getBreed(), and overrode speak() to provide dog-specific behaviour.
The extends Keyword
extends declares that a class inherits from another:
public class Dog extends Animal { ... }
// child parent
Java supports single inheritance only – a class can extend exactly one parent. It cannot extend two classes simultaneously.
The super Keyword
super refers to the parent class. It has two main uses:
1. Calling the parent constructor:
public Dog(String name, int age, String breed) {
super(name, age); // calls Animal(String, int)
this.breed = breed;
}
The super(...) call MUST be the first line in the child constructor. It passes values to the parent constructor to initialise the inherited attributes. If you do not call super(...), Java automatically calls super() (the no-argument parent constructor) – which will fail if the parent does not have one.
2. Calling a parent method:
@Override
public String speak() {
return super.speak() + " Woof!"; // calls Animal's speak() then adds to it
}
super(...)must be the first statement in a child constructor. This ensures the parent part of the object is initialised before the child adds its own attributes. Forgetting this is a common compile error.
What is Inherited?
A child class inherits:
- All
publicandprotectedmethods - All
publicandprotectedattributes - The parent’s public interface
A child class does NOT inherit:
privateattributes (they exist in the object but cannot be accessed directly – use getters)- Constructors (the child must define its own and call
super(...))
public class Animal {
private String name; // NOT directly accessible in Dog
protected int age; // accessible in Dog
public String getName() { return name; } // inherited by Dog
}
public class Dog extends Animal {
public void printInfo() {
// System.out.println(name); // ERROR -- name is private in Animal
System.out.println(getName()); // OK -- getName() is public
System.out.println(age); // OK -- age is protected
}
}
Constructor Chaining
When you create a Dog, Java must first create the Animal part of the object. This is constructor chaining – the child constructor calls the parent constructor, which initialises the parent attributes before the child constructor initialises its own.
new Dog("Max", 3, "Labrador")
│
▼
Dog constructor runs:
│
├── super("Max", 3) → Animal constructor sets name="Max", age=3
│
└── this.breed = "Labrador" → Dog constructor sets breed
Advantages of Inheritance
| Advantage | How |
|---|---|
| Code reuse | Common attributes and methods are written once in the parent, inherited by all children |
| Extensibility | New child classes can be added without modifying existing code |
| Maintainability | Fixing a bug in the parent automatically fixes it in all children |
| Logical hierarchy | Reflects real-world relationships (Dog is-a Animal, Car is-a Vehicle) |
Disadvantages of Inheritance
| Disadvantage | How |
|---|---|
| Tight coupling | Child depends on parent’s implementation; changes to the parent can break children |
| Fragile base class | Modifying a parent class can have unintended effects on all subclasses |
| Limited flexibility | Java allows only single inheritance – a class can have only one parent |
Inheritance creates “is-a” relationships and enables code reuse, extensibility, easier debugging, and maintainability. These are the exact advantages IB mark schemes award marks for.
UML Notation
Inheritance is shown with a solid line and a closed triangle pointing to the parent:
+------------------+
| Animal |
+------------------+
| - name: String |
| - age: int |
+------------------+
| + getName(): ... |
| + speak(): ... |
+------------------+
△
|
+------------------+
| Dog |
+------------------+
| - breed: String |
+------------------+
| + getBreed(): ...|
| + speak(): ... |
+------------------+
Worked Examples
Example 1: Building a Class Hierarchy
Scenario: A school has different types of people: students and teachers. Both have names and ages. Students have a grade; teachers have a subject.
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() { return name; }
public int getAge() { return age; }
}
public class Student extends Person {
private int grade;
public Student(String name, int age, int grade) {
super(name, age);
this.grade = grade;
}
public int getGrade() { return grade; }
}
public class Teacher extends Person {
private String subject;
public Teacher(String name, int age, String subject) {
super(name, age);
this.subject = subject;
}
public String getSubject() { return subject; }
}
Student s = new Student("Alice", 16, 11);
Teacher t = new Teacher("Mr. Smith", 35, "CS");
System.out.println(s.getName() + " Grade " + s.getGrade());
System.out.println(t.getName() + " teaches " + t.getSubject());
Output:
Alice Grade 11
Mr. Smith teaches CS
Both Student and Teacher inherit getName() and getAge() from Person. Each adds its own specific attribute and getter.
Example 2: The Racer Hierarchy
Inspired by the classic IB teaching example:
public class Racer {
private String name;
private int position;
public Racer(String name) {
this.name = name;
this.position = 0;
}
public String getName() { return name; }
public int getPosition() { return position; }
public void move() {
position = position + 1; // default: move 1 step
}
}
public class Hare extends Racer {
public Hare(String name) {
super(name);
}
@Override
public void move() {
// 30% chance of jumping 5 steps, 70% chance of sleeping
if (Math.random() < 0.3) {
// Jump forward 5 positions
for (int i = 0; i < 5; i++) {
super.move(); // reuse parent's move()
}
}
// else: do nothing (sleep)
}
}
public class Tortoise extends Racer {
public Tortoise(String name) {
super(name);
}
@Override
public void move() {
super.move(); // always moves exactly 1 step
}
}
The Hare and Tortoise both IS-A Racer but override move() with different strategies. This sets up polymorphism (covered in the next page).
Quick Check
Q1. Which keyword is used to create a child class from a parent class?
Q2. Where must super(...) appear in a child constructor?
Q3. Can a child class directly access a parent's private attributes?
Q4. Which is an advantage of inheritance?
Q5. Which is a disadvantage of inheritance?
Trace Exercise
Trace the creation of a Student object. Track how constructor chaining works.
Trace: Constructor Chaining
Student s = new Student("Alice", 16, 11);What happens in order?
| Step | Constructor | name | age | grade |
|---|---|---|---|---|
| 1. super("Alice", 16) called | -- | |||
| 2. this.grade = 11 |
Spot the Error
This code does not compile. The constructor is missing a required call. Click the line where the missing statement should be inserted, then pick the fix.
Pick what should be added before this.grade = grade;:
Predict the Output
What does this print?
Dog d = new Dog("Max", 3, "Labrador");
System.out.println(d.getName() + " says " + d.speak() + " (" + d.getBreed() + ")"); Practice Exercises
Core
-
Build a hierarchy – Create a
Vehicleparent class withmake(String),year(int), andgetDescription(). Create two child classes:Car(addsnumDoors) andMotorcycle(addshasSidecarboolean). Each child should callsuper(...)in its constructor. - Identify inheritance – For each pair, state whether inheritance is appropriate and explain why:
- (a)
TextbookandBook - (b)
LaptopandBattery - (c)
TeacherandPerson - (d)
PlaylistandSong
- (a)
- Trace constructor chaining – Given
Vehicle->Car->ElectricCar, trace what happens when you create anElectricCar("Tesla", 2024, 4, 350)where 350 is the battery range in km. Show which constructor runs first.
Extension
-
Override a method – Add a
getDescription()method to bothCarandMotorcyclethat overrides the parent’s version. Car’s should include door count; Motorcycle’s should mention the sidecar status. Usesuper.getDescription()to include the parent’s output. -
Advantages and disadvantages – A student argues that inheritance should be used whenever two classes share any attributes. Explain why this is wrong, giving an example of when aggregation would be more appropriate even though the classes share attributes.
Challenge
- Full system with inheritance – Design a banking system with
BankAccount(parent),SavingsAccount(adds interest rate andaddInterest()method), andCheckingAccount(adds overdraft limit and modifiedwithdraw()that allows negative balance up to the limit). Draw the UML and implement all three classes.
Connections
- Prerequisites: Classes and Objects – creating classes with attributes and methods
- Prerequisites: Constructors – understanding how constructors initialise objects
- Prerequisites: Aggregation – understanding when to use has-a vs is-a
- Next: Method Overriding – deeper dive into
@Overrideand changing parent behaviour - Forward: Polymorphism – using parent-type references to hold child objects