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.

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.

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.

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.

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.

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.

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.

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.

Key rules for using extends and super in Java
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."
⚠️ 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.

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
Step 1 — Define the SuperclassWe 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
Step 2 — Define the Subclass Using extendsNow 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
Step 3 — Create a Dog ObjectIn our main method, we instantiate a Dog.
Dog myDog = new Dog("Rex", 3, "Labrador");
4
Step 4 — Trace the Constructor ChainWhen 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
Step 5 — Call Methods and Observe PolymorphismNow 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)

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.

Comparing code-reuse approaches in Java
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.
🎯 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.

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.

How inheritance connects to advanced Java concepts
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.

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.

Practice Problems

PROBLEM 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?
PROBLEM 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; } }
PROBLEM 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); } }
PROBLEM 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.
PROBLEM 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.

Lesson 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