Menu
Courses / Java Basic / inheritance and polymorphism

inheritance and polymorphism

09 / 10 Part of Java Basic

The Four Pillars of OOP


Java's object-oriented model rests on four core principles. We touched on encapsulation in the last topic — now let's cover the rest.



   
   
       
       
       
       
   
PillarMeaning
EncapsulationHiding internal data behind private fields and public methods
InheritanceA class acquiring fields and methods from another class
PolymorphismThe same method behaving differently depending on the object
AbstractionHiding complex implementation details behind a simple interface


Inheritance


Inheritance lets one class (the subclass) reuse fields and methods from another (the superclass), using the extends keyword. This avoids duplicating code between related classes.



// Superclass
public class Animal {
    String name;

    Animal(String name) {
        this.name = name;
    }

    void eat() {
        System.out.println(name + " is eating.");
    }
}

// Subclass
public class Dog extends Animal {
    Dog(String name) {
        super(name); // calls the Animal constructor
    }

    void bark() {
        System.out.println(name + " says Woof!");
    }
}


Dog myDog = new Dog("Rex");
myDog.eat();  // inherited from Animal: "Rex is eating."
myDog.bark(); // defined in Dog: "Rex says Woof!"



    Note: super(name) calls the constructor of the parent class. It must be the first line inside the subclass constructor.


Method Overriding


A subclass can provide its own version of a method that already exists in the superclass, using the @Override annotation.


public class Animal {
    void makeSound() {
        System.out.println("Some generic animal sound");
    }
}

public class Cat extends Animal {
    @Override
    void makeSound() {
        System.out.println("Meow");
    }
}

Animal genericAnimal = new Animal();
Animal myCat = new Cat();

genericAnimal.makeSound(); // Some generic animal sound
myCat.makeSound();         // Meow


Polymorphism in Action


Polymorphism means "many forms" — the same reference type can behave differently depending on the actual object it points to at runtime. This is often shown by storing subclass objects in a superclass-typed array or list.


Animal[] animals = { new Dog("Rex"), new Cat("Whiskers"), new Animal("Generic") };

for (Animal a : animals) {
    a.makeSound(); // calls the correct overridden version for each object
}


Abstract Classes


An abstract class cannot be instantiated directly — it exists to be extended. It can define abstract methods (no body) that subclasses must implement.


abstract class Shape {
    abstract double area(); // no implementation here

    void describe() {
        System.out.println("This shape has an area of " + area());
    }
}

class Circle extends Shape {
    double radius;

    Circle(double radius) {
        this.radius = radius;
    }

    @Override
    double area() {
        return Math.PI * radius * radius;
    }
}

Circle c = new Circle(5);
c.describe(); // This shape has an area of 78.53981633974483


Interfaces


An interface defines a contract — a set of method signatures that any implementing class must provide. Unlike abstract classes, a class can implement multiple interfaces.


interface Flyable {
    void fly();
}

class Bird implements Flyable {
    @Override
    public void fly() {
        System.out.println("The bird flies through the sky.");
    }
}


Inheritance vs Interface — Quick Comparison



   
   
       
       
       
   
Abstract ClassInterface
Can have both implemented and abstract methodsTraditionally only method signatures (Java 8+ allows default methods)
A class can extend only one abstract classA class can implement multiple interfaces
Use when classes share common codeUse when unrelated classes need to share a capability



    Coming up next: Exception handling — how to gracefully deal with errors when things go wrong at runtime.