Runtime Polymorphism

Dynamic Method Dispatch

A parent-type variable can hold a child object. When you call an overridden method, the JVM looks at the actual object at runtime, not the variable type.

Example

public class Main {
    public static void main(String[] args) {
        Shape[] shapes = { new Circle(1), new Rectangle(2, 3), new Circle(2) };
        double total = 0;
        for (Shape s : shapes) {
            System.out.printf("%-10s area = %.2f%n", s.name(), s.area());
            total += s.area();
        }
        System.out.printf("Total area = %.2f%n", total);
    }
}

class Shape {
    double area() { return 0; }
    String name() { return "Shape"; }
}

class Circle extends Shape {
    double r;
    Circle(double r) { this.r = r; }
    @Override double area() { return Math.PI * r * r; }
    @Override String name() { return "Circle"; }
}

class Rectangle extends Shape {
    double w, h;
    Rectangle(double w, double h) { this.w = w; this.h = h; }
    @Override double area() { return w * h; }
    @Override String name() { return "Rectangle"; }
}

Output

Circle     area = 3.14
Rectangle  area = 6.00
Circle     area = 12.57
Total area = 21.71

Fields Are Not Polymorphic

Example

Only methods are dispatched at runtime. Fields and static methods are resolved from the variable type.

public class Main {
    public static void main(String[] args) {
        Parent p = new Child();
        System.out.println(p.name);        // field: variable type (Parent)
        System.out.println(p.getName());   // method: object type (Child)
        p.hello();                         // static: variable type (Parent)
    }
}

class Parent {
    String name = "parent";
    String getName() { return name; }
    static void hello() { System.out.println("static hello from Parent"); }
}

class Child extends Parent {
    String name = "child";
    @Override String getName() { return name; }
    static void hello() { System.out.println("static hello from Child"); }
}

Output

parent
child
static hello from Parent

Tip: This is a favourite interview trick question. Avoid declaring a field with the same name in parent and child in real code.