Java • Object-Oriented Programming

Inheritance with super — Extend a class and use super to call superclass constructors/methods

Learn how Java classes share and extend behavior through inheritance and the super keyword.

Java programming emblem with a coffee cup, code braces, and terminal
Inside this lesson 10 sections 5 questions 5 figures

SECTION 1

Historical Context & Motivation

Imagine you are building a video game with dozens of character types — warriors, mages, archers, and healers. Each character has a name, health points, and a method to take damage. Without some way to share that common code, you would copy and paste the same fields and methods into every single class. That is tedious, error-prone, and a nightmare to maintain. Inheritance was invented to solve exactly this problem: it lets one class automatically receive the fields and methods of another, so you only write the shared code once.

The idea of inheritance did not appear overnight. It grew out of decades of research into how programmers can organize and reuse code more effectively. The timeline below highlights the key milestones that led to Java's inheritance model and the super keyword.

1967 • Simula 67 Introduces Classes & Inheritance

Norwegian computer scientists Ole-Johan Dahl and Kristen Nygaard created Simula 67, the first language to support classes, objects, and inheritance. Their goal was to model real-world simulations.

1972 • Smalltalk Refines the Concept

Alan Kay's Smalltalk language popularized the term "object-oriented programming" and introduced the idea of sending messages between objects, with subclasses inheriting behavior from superclasses.

1983 • C++ Brings OOP to the Mainstream

Bjarne Stroustrup extended the C language with classes and inheritance. C++ demonstrated that OOP could be efficient enough for systems programming.

1995 • Java Launches with Single Inheritance & super

James Gosling and his team at Sun Microsystems released Java, which simplified C++ by supporting only single inheritance and providing the super keyword to cleanly access parent-class constructors and methods.

The central question inheritance answers is: How can we write shared behavior once and let many classes reuse and customize it? Java's answer involves the extends keyword to establish a parent-child relationship and the super keyword to reach back into the parent class when needed.

SECTION 2

Core Principles & Definitions

Before diving into code, let's nail down the key vocabulary. Understanding these terms clearly will make everything else in the lesson click.

1

Superclass (Parent Class)

The class whose fields and methods are inherited. Also called the base class. In class Dog extends Animal, the superclass is Animal.
2

Subclass (Child Class)

The class that inherits from another. It gains all non-private members of the superclass and can add its own. In the example above, Dog is the subclass.
3

extends Keyword

The Java keyword used to declare that one class inherits from another. Java supports single inheritance, meaning a class can extend only one superclass.
4

super Keyword

A reference to the superclass. Use super() to call a superclass constructor and super.methodName() to call a superclass method from the subclass.
5

Method Overriding

When a subclass provides its own version of a method that already exists in the superclass, with the same name and parameters. The subclass version replaces the inherited one.
✦

KEY TAKEAWAY

Think of inheritance like a family recipe book. Your grandparent writes the original recipe (the superclass). You inherit the entire recipe automatically, but you can tweak the seasoning (override a method) while still using super to call back to the original steps whenever you want the classic flavor.

One important rule to remember: the super() call inside a constructor must be the very first statement. If you don't write it explicitly, Java inserts super() (the no-argument version) for you behind the scenes. This guarantees that the parent is always initialized before the child adds anything new.

SECTION 3

Visual Explanation — The Inheritance Hierarchy

The diagram below illustrates a simple class hierarchy. An Animal superclass holds shared fields and methods. Two subclasses, Dog and Cat, extend it, inheriting everything and adding their own specialized behavior. Arrows point from child to parent to show the "extends" relationship.

Animal- name : String- age : int+ Animal(name, age)+ speak() : StringDog- breed : String+ Dog(name, age, breed) → super(name, age)+ speak() : String // overrides AnimalCat- isIndoor : boolean+ Cat(name, age, isIndoor) → super(name, age)+ speak() : String // overrides Animalextendsextends▲ Arrows point from subclass to superclass ("is-a" relationship)
Both Dog and Cat inherit name, age, and the speak() method from Animal. Each subclass calls super(name, age) in its constructor and overrides speak() with its own version.

Notice that the subclasses do not redeclare name or age. Those fields are inherited automatically. The constructor in each subclass uses super(name, age) to pass the values up to Animal's constructor, which handles initializing them. This keeps the code DRY (Don't Repeat Yourself) — a core principle of good software design.

SECTION 4

How super Works Under the Hood

Two Uses of super

The super keyword has exactly two uses in Java. First, super() calls a superclass constructor. You place it as the first line of a subclass constructor and pass the arguments the parent constructor expects. Second, super.methodName() calls a superclass method. This is useful when you override a method but still want to reuse the parent's version as part of your new implementation.

Constructor Chaining

When you create a new Dog object, Java does not just run the Dog constructor in isolation. Instead, it follows a chain: the Dog constructor calls super(), which runs the Animal constructor first. The Animal constructor itself implicitly calls super() on Object (Java's built-in root class). This is called constructor chaining, and it ensures that every level of the hierarchy is properly initialized from top to bottom.

Constructor Chaining: new Dog("Rex", 3, "Labrador")Object()Java root classAnimal(name, age)Sets name & ageDog(n, a, breed)Sets breedExecution Order① super(name, age)② implicit super()③ Object init done④ Animal init done⑤ Dog init done= super() call (upward)= initialization completes (returns downward)
The pink arrows show the super() calls going up the chain. The green arrows show each constructor finishing and returning control down to the subclass. The superclass is always initialized before the subclass.

Calling super.method()

Sometimes when you override a method, you don't want to replace the parent's behavior entirely — you want to add to it. For example, suppose Animal.speak() returns "I am an animal". In Dog, you could write:

💡

Code Snippet

@Override public String speak() { return super.speak() + " and I bark!"; }

Here, super.speak() calls the Animal version of the method, and the subclass adds its own piece. The result would be "I am an animal and I bark!". Without super, calling speak() inside Dog would recursively call the Dog version — which is not what you want.

SECTION 5

Rules, Patterns, and Common Mistakes

Now that you understand the mechanics, let's catalog the specific rules Java enforces and the common mistakes beginners make. The table below is a handy reference you can come back to while coding.

RuleWhat It MeansWhat Happens If You Break It
super() must be line 1In a subclass constructor, the call to super() must appear before any other statement.Compiler error: "call to super must be first statement in constructor."
Arguments must matchThe arguments in super(...) must match one of the superclass's constructor signatures.Compiler error: "no suitable constructor found."
Implicit super()If you omit super(), Java auto-inserts the no-argument version.If the superclass has no no-arg constructor, you get a compiler error.
Can't use super in static contextsuper refers to an instance, so it cannot appear in a static method.Compiler error: "non-static variable super cannot be referenced from a static context."
Single inheritance onlyA Java class can extend only one superclass (no multiple inheritance of classes).Compiler error. Use interfaces if you need multiple "types."

Key rules for using extends and super in Java

⚠

Common Mistake Alert

A very common beginner mistake is defining a parameterized constructor in the superclass but forgetting to add a no-argument constructor. When the subclass doesn't explicitly call super(args), Java tries to call super() automatically — and fails because no such constructor exists. Always either provide a no-arg constructor in the superclass or explicitly call super(args) in every subclass constructor.

SECTION 6

Worked Example — Building an Animal Hierarchy

Let's walk through a complete example step by step. We will create an Animal superclass and a Dog subclass, then trace what happens when we create a Dog object.

Creating a Dog That Extends Animal

  1. 1

    Step 1 — Define the Superclass

    We start with the Animal class. It has two private fields (name and age), a constructor that initializes them, and a speak() method.
    public class Animal { private String name; private int age; public Animal(String name, int age) { this.name = name; this.age = age; } public String speak() { return name + " makes a sound."; } public String getName() { return name; } public int getAge() { return age; } }
  2. 2

    Step 2 — Define the Subclass Using extends

    Now we create Dog using extends Animal. It adds a breed field and overrides speak(). Notice that the constructor calls super(name, age) as its very first line.
    public class Dog extends Animal { private String breed; public Dog(String name, int age, String breed) { super(name, age); // calls Animal's constructor this.breed = breed; } @Override public String speak() { return getName() + " barks! Woof!"; } public String getBreed() { return breed; } }
  3. 3

    Step 3 — Create a Dog Object

    In our main method, we instantiate a Dog.
    Dog myDog = new Dog("Rex", 3, "Labrador");
  4. 4

    Step 4 — Trace the Constructor Chain

    When new Dog("Rex", 3, "Labrador") runs, Java enters the Dog constructor and immediately encounters super("Rex", 3). This triggers the Animal constructor, which sets name = "Rex" and age = 3. Control returns to the Dog constructor, which then sets breed = "Labrador".
  5. 5

    Step 5 — Call Methods and Observe Polymorphism

    Now we can call methods on our myDog object. Because Dog overrides speak(), the overridden version runs.
    System.out.println(myDog.speak()); // Rex barks! Woof! System.out.println(myDog.getName()); // Rex (inherited) System.out.println(myDog.getAge()); // 3 (inherited) System.out.println(myDog.getBreed()); // Labrador (Dog-specific)

SECTION 7

Inheritance vs. Other Approaches

Inheritance is powerful, but it is not the only way to share code between classes. Understanding when to use inheritance versus other techniques is an important skill. The table below compares inheritance with two common alternatives.

ApproachHow It WorksBest Used When
Inheritance (extends)Subclass automatically receives all non-private members of the superclass. Represents an "is-a" relationship.The subclass truly is a specialized version of the superclass (e.g., Dog is-a Animal).
Composition (has-a)A class stores a reference to another class as a field and delegates work to it.The relationship is "has-a" (e.g., a Car has-an Engine). More flexible than inheritance.
Interfaces (implements)A class promises to provide certain methods. Multiple interfaces can be implemented.You need a common contract without shared implementation, or you need multiple types.

Comparing code-reuse approaches in Java

🎯

WHEN TO CHOOSE INHERITANCE

Use the "is-a" test. If you can naturally say "a Dog is an Animal," inheritance fits. If you'd say "a Car has an Engine" instead, use composition. Think of inheritance as a committed relationship — the subclass is permanently linked to the superclass. Composition is more like hiring a contractor: you can swap out the helper object anytime.

SECTION 8

Connection to Advanced OOP Concepts

Inheritance with super is foundational, but it opens the door to more powerful concepts in Java. As you grow as a programmer, you will encounter ideas that build directly on what you've learned here.

What You Know NowWhat Comes Next
Extending a concrete classAbstract classes — a superclass that cannot be instantiated and may contain abstract methods that subclasses must implement.
Overriding a single methodPolymorphism — using a superclass reference to call overridden methods, letting the JVM pick the correct version at runtime.
Single inheritance with extendsInterfaces — a class can implement multiple interfaces, gaining a form of multiple inheritance of type (not implementation).
Using super to call parent methodsThe protected access modifier — grants subclasses direct access to fields/methods that outsiders cannot see, offering a middle ground between public and private.

How inheritance connects to advanced Java concepts

Mastering extends and super now gives you a strong foundation. When you encounter abstract classes, polymorphism, and interfaces later, they will feel like natural extensions of what you already know — pun intended.

SECTION 9

Practice Problems

Question 1: CONCEPTUAL

In your own words, explain why the super() call must be the first statement in a subclass constructor. What could go wrong if Java allowed other statements to come first?
Show answer
The superclass portion of the object must be fully initialized before the subclass tries to use any inherited fields or methods. If Java allowed statements before super(), the subclass constructor might try to access inherited fields that have not been set yet, leading to unpredictable or incorrect behavior. By enforcing super() first, Java guarantees a safe, top-down initialization order from Object all the way down to the most specific subclass.

Question 2: BASIC CALCULATION

Given the following superclass, write a subclass called Circle that extends Shape and adds a radius field. Use super to call the parent constructor. public class Shape { private String color; public Shape(String color) { this.color = color; } public String getColor() { return color; } }
Show answer
public class Circle extends Shape { private double radius; public Circle(String color, double radius) { super(color); // calls Shape(String) this.radius = radius; } public double getRadius() { return radius; } } The key detail is that super(color) must appear as the first line of the Circle constructor. It delegates the initialization of the color field to Shape's constructor, and then Circle handles its own radius.

Question 3: INTERMEDIATE

The following code will not compile. Identify the error and fix it. public class Vehicle { private int speed; public Vehicle(int speed) { this.speed = speed; } } public class Truck extends Vehicle { private int payload; public Truck(int speed, int payload) { this.payload = payload; super(speed); } }
Show answer
The error is that super(speed) is on the second line of the Truck constructor instead of the first line. Java requires super() to be the very first statement. The fix is to swap the two lines: public Truck(int speed, int payload) { super(speed); // MUST be first this.payload = payload; } With this fix, the Vehicle portion initializes speed before Truck sets payload.

Question 4: APPLIED

Design a two-class hierarchy for a school system. Create a Person superclass with name and age fields, and a Student subclass that adds gpa. Override a toString() method so that Student.toString() uses super.toString() and appends the GPA. Write the complete code for both classes.
Show answer
public class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return name + " (age " + age + ")"; } } public class Student extends Person { private double gpa; public Student(String name, int age, double gpa) { super(name, age); this.gpa = gpa; } @Override public String toString() { return super.toString() + ", GPA: " + gpa; } } Calling new Student("Alice", 16, 3.9).toString() returns "Alice (age 16), GPA: 3.9". The super.toString() call reuses the Person version so we don't repeat the name and age formatting logic.

Question 5: CRITICAL THINKING

Consider this scenario: class A has a method greet() that returns "Hello". Class B extends A and overrides greet() to return "Hi". Class C extends B and overrides greet() to return super.greet() + " there". What does new C().greet() return? Could class C directly access A's version of greet() using super.super.greet()? Explain why or why not.
Show answer
new C().greet() returns "Hi there". Inside C.greet(), the call super.greet() refers to B.greet(), which returns "Hi". Java concatenates that with " there" to produce "Hi there". No, Java does not allow super.super.greet(). The language deliberately prevents skipping levels in the hierarchy because it would break encapsulation — class B chose to override greet() for a reason, and allowing grandchild classes to bypass that decision would undermine the design.

SUMMARY

Lesson Summary

Summary

Inheritance lets a subclass automatically receive the fields and methods of a superclass by using the extends keyword. This supports the is-a relationship — a Dog is-an Animal, a Student is-a Person. The shared code lives in the superclass, and each subclass adds its own specialized fields and methods, keeping your codebase clean and maintainable.

The super keyword is your bridge back to the parent class. Use super() in constructors (always as the first statement) to initialize the inherited fields, and use super.methodName() in overridden methods when you want to build on the parent's behavior rather than replace it entirely. Remember: Java enforces single inheritance for classes, and the constructor chain always runs from the topmost superclass down to the most specific subclass.

Varsity Tutors • Java • Inheritance with super