Inheritance
Reuse and extend existing classes using extends - build class hierarchies where child classes inherit fields and methods from parent classes.
Overview
Key Points
- •extends keyword: `class Dog extends Animal`
- •Child inherits all non-private fields and methods from the parent
- •Override a parent method by redefining it with the same signature in the child; use @Override annotation
- •super.method() calls the parent class version of a method
- •super(args) in a constructor calls the parent constructor - must be first statement
- •Java supports single inheritance only - a class can extend one class
- •Every class implicitly extends Object if no extends is specified
- •instanceof checks whether an object is of a particular type
Examples
Basic inheritance and method override
class Animal {
String name;
Animal(String name) {
this.name = name;
}
void speak() {
System.out.println(name + " makes a sound.");
}
void breathe() {
System.out.println(name + " breathes.");
}
}
class Dog extends Animal {
String breed;
Dog(String name, String breed) {
super(name); // calls Animal(name)
this.breed = breed;
}
@Override
void speak() {
System.out.println(name + " barks: Woof!");
}
void fetch() {
System.out.println(name + " fetches the ball!");
}
}
class Cat extends Animal {
Cat(String name) {
super(name);
}
@Override
void speak() {
System.out.println(name + " meows: Meow!");
}
}
public class Main {
public static void main(String[] args) {
Dog rex = new Dog("Rex", "Labrador");
Cat kitty = new Cat("Kitty");
rex.speak(); // Rex barks: Woof!
rex.breathe(); // Rex breathes. (inherited)
rex.fetch(); // Rex fetches the ball!
kitty.speak(); // Kitty meows: Meow!
kitty.breathe(); // Kitty breathes. (inherited)
}
}breathe() is defined once in Animal and automatically available in Dog and Cat without copying it.
super - calling parent constructor and parent methods
class Shape {
String colour;
Shape(String colour) {
this.colour = colour;
}
String describe() {
return "A " + colour + " shape";
}
}
class Circle extends Shape {
double radius;
Circle(String colour, double radius) {
super(colour); // calls Shape(colour)
this.radius = radius;
}
@Override
String describe() {
return super.describe() + " (circle, r=" + radius + ")";
}
double area() {
return Math.PI * radius * radius;
}
}
public class Main {
public static void main(String[] args) {
Circle c = new Circle("red", 5.0);
System.out.println(c.describe()); // A red shape (circle, r=5.0)
System.out.printf("Area: %.2f%n", c.area());
}
}super.describe() runs the parent's describe() and the child appends its own info.
instanceof and polymorphism
public class Main {
public static void main(String[] args) {
Animal[] animals = {
new Dog("Rex", "Lab"),
new Cat("Kitty"),
new Dog("Max", "Poodle")
};
for (Animal a : animals) {
a.speak(); // calls Dog.speak() or Cat.speak() based on actual type
if (a instanceof Dog) {
Dog d = (Dog) a;
d.fetch(); // can call Dog-specific method after casting
}
}
}
}A Dog reference can be stored in an Animal variable (upcasting). instanceof lets you check the actual type before downcasting.
Common Mistakes
- Forgetting super(args) in the child constructor when the parent has no no-arg constructor - compile error
- Overriding without @Override annotation - if you misspell the method name you create a new method instead of overriding
- Calling super() after other statements in the constructor - super() must be first
- Inheriting too deeply: 5+ levels of inheritance is usually a design smell; consider composition instead
Note
Before using inheritance, ask: "Is the child really a more specific version of the parent?" If the relationship is "has-a" rather than "is-a," use composition (a field) instead.
Exercises
Write Java code and click Run to execute it instantly. When your output looks correct, mark as done.
Completed: 0 / 4 exercises
Knowledge Check
Question 1 of 4