Inheritance in Java: Reusing Code with extends, super and Overriding
Learn inheritance in Java — the second pillar of OOP. Understand parent and child classes, the extends keyword, method overriding, and super, all with clear examples.
Imagine you're writing classes for a Dog, a Cat, and a Cow. They all have a name, they all eat, they all sleep — you'd be copying the same code into all three. Inheritance solves exactly this: it lets one class reuse the fields and methods of another. It's the second pillar of OOP, and it's all about writing code once and sharing it.
The idea: a parent and its children
Inheritance creates an "is-a" relationship. A dog is an animal, a car is a vehicle. So we put the shared stuff in a parent class (also called a superclass or base class), and the specific classes extend it, automatically getting everything the parent has.
- Parent / superclass — the general class with the shared code (e.g.
Animal). - Child / subclass — a specific class that extends the parent and adds its own extras (e.g.
Dog).
The extends keyword
Here's a parent Animal and a child Dog that inherits from it:
// PARENT class public class Animal { String name; void eat() { System.out.println(name + " is eating."); } } // CHILD class — inherits everything from Animal public class Dog extends Animal { void bark() { System.out.println(name + " says Woof!"); } }
Notice Dog never declared name or eat() — it got them for free from Animal via extends. Now watch it use both its inherited and its own abilities:
Dog d = new Dog(); d.name = "Bruno"; d.eat(); // inherited from Animal → "Bruno is eating." d.bark(); // Dog's own method → "Bruno says Woof!"
That's the whole win: write eat() once in Animal, and every animal type gets it.
Overriding: a child doing things its own way
Sometimes a child needs to change an inherited method. This is called overriding — you redefine the method in the child, and Java uses the child's version. Mark it with @Override (a helpful annotation that catches mistakes):
public class Cat extends Animal { // same method name, but Cat's own behaviour @Override void eat() { System.out.println(name + " eats quietly and delicately."); } }
Now cat.eat() runs the Cat version, not the Animal one. (This idea powers polymorphism, the very next lesson.)
The super keyword
super refers to the parent. It's most useful for two things: calling the parent's constructor, and calling the parent's version of a method you've overridden:
public class Dog extends Animal { @Override void eat() { super.eat(); // run Animal's eat() first... System.out.println("...then wags its tail."); // ...then add more } }
Dog is an Animal ✓). If it's really a "has-a" relationship (a Car has an Engine), don't use inheritance — just give the class a field. A common beginner mistake is over-using inheritance; save it for genuine is-a cases.Inheritance clicked for me the day I stopped copy-pasting the same methods into five classes and moved them into one parent. Suddenly a fix in the parent improved every child at once. That said, I've also learned the newer lesson the hard way: reach for inheritance only when it's a real is-a relationship — otherwise a simple field ("has-a") keeps your design far cleaner.
Key takeaways
- Inheritance lets a child class reuse a parent's fields and methods via
extends. - Use it for genuine "is-a" relationships (Dog is an Animal).
- Override a method (with
@Override) to give a child its own version. supercalls the parent's constructor or its original method.
← Previous: Lesson 14 — Encapsulation in Java
Next: Lesson 16 — Polymorphism in Java →