Java Polymorphism

Polymorphism means “many forms”. One method call can behave in different ways depending on the real object. It is the most powerful idea of object oriented programming.

Parent reference, child object

class Shape {
    double area() {
        return 0;
    }
}

class Circle extends Shape {
    double r;
    Circle(double r) { this.r = r; }

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

class Rectangle extends Shape {
    double w, h;
    Rectangle(double w, double h) { this.w = w; this.h = h; }

    @Override
    double area() {
        return w * h;
    }
}

public class Main {
    public static void main(String[] args) {
        Shape[] shapes = { new Circle(2), new Rectangle(3, 4), new Circle(1) };

        double total = 0;
        for (Shape s : shapes) {
            System.out.printf("%s area = %.2f%n", s.getClass().getSimpleName(), s.area());
            total += s.area();
        }
        System.out.printf("Total area = %.2f%n", total);
    }
}
Output

Circle area = 12.57
Rectangle area = 12.00
Circle area = 3.14
Total area = 27.71

The variable type is Shape, but Java calls the area() of the real object. This is called dynamic method dispatch, decided when the program runs. We can add a new shape later and this loop does not change.

Compile time and run time polymorphism

KindAlso calledHow
Compile timeStaticMethod overloading: chosen by the compiler from the parameters
Run timeDynamicMethod overriding: chosen by the JVM from the real object

instanceof and casting

A parent reference can only use the methods of the parent. To use a child method, check the type and cast:

class Animal { }

class Dog extends Animal {
    void bark() { System.out.println("Woof!"); }
}

class Cat extends Animal { }

public class Cast {
    public static void main(String[] args) {
        Animal a = new Dog();
        // a.bark();                 // error: Animal has no bark()

        if (a instanceof Dog) {
            Dog d = (Dog) a;
            d.bark();
        }

        Animal b = new Cat();
        if (b instanceof Dog) {
            System.out.println("dog");
        } else {
            System.out.println("not a dog");
        }
    }
}
Output

Woof!
not a dog

A wrong cast throws a ClassCastException:

class Animal { }
class Dog extends Animal { }
class Cat extends Animal { }

public class Wrong {
    public static void main(String[] args) {
        Animal a = new Cat();
        Dog d = (Dog) a;
    }
}
Output

Exception in thread "main" java.lang.ClassCastException: class Cat cannot be cast to class Dog (Cat and Dog are in unnamed module of loader com.sun.tools.javac.launcher.MemoryClassLoader @4cf4d528)
at Wrong.main(Wrong.java:8)

Pattern matching for instanceof (Java 16+)

The check and the cast can be done in one step:

class Animal { }

class Dog extends Animal {
    void bark() { System.out.println("Woof!"); }
}

public class Pattern {
    public static void main(String[] args) {
        Animal a = new Dog();
        if (a instanceof Dog d) {      // d is ready to use
            d.bark();
        }
    }
}
Output

Woof!

Fields are not polymorphic

Only methods are overridden. Fields are chosen by the variable type, not by the object. This is a common interview question, so remember it.

Note: Write your code against the parent type (or an interface), and let the objects decide the behavior. Next: Java Abstract Classes.

Congratulations! Chapter Finished. Learn more about the similar topics:
Exercises & Assignments
No Content Found.
Interview Questions & Answers
No Content Found.