Lesson 10 / 25

Compile-Time Polymorphism: Overloading

Use method and operator overloading and know how overloads are resolved.

Same name, different parameters

Polymorphism means "many forms": one name or interface, several behaviours. Compile-time (static) polymorphism is resolved by the compiler from the declared types of the arguments. Its main form is method overloading: several methods with the same name but different parameter lists (number, types or order of parameters), such as print(int), print(String) and print(String, int). The return type alone cannot distinguish overloads. When choosing an overload, Java prefers exact matches, then widening primitive conversions, then boxing, then varargs, which occasionally produces surprises with null arguments or mixes of int and long. Operator overloading lets classes define operators: C++ (operator+), C# and Python (__add__, __eq__, __lt__) support it; Java does not, apart from built-in + for strings. Use overloading for genuinely equivalent operations on different inputs, not for unrelated behaviours that happen to share a name.

Many forms of one name

Overloads share a name but differ in parameters; the compiler picks one from the argument types.

One label at the top branching into three boxes of different shapes, each receiving a differently shaped input arrow.
Figure 4.1 — Overload resolution by parameter types.

Method overloading in Java and operator overloading in Python

The compiler chooses a Java overload from the argument types.

public class Area {
    static double of(double radius)                { return Math.PI * radius * radius; }
    static double of(double width, double height) { return width * height; }
    static double of(double a, double b, double c) {        // triangle, Heron's formula
        double s = (a + b + c) / 2;
        return Math.sqrt(s * (s - a) * (s - b) * (s - c));
    }
}

double circle = Area.of(2.0);
double rect   = Area.of(3.0, 4.0);
double tri    = Area.of(3.0, 4.0, 5.0);

// Python: operator overloading with special methods
// class Vector:
//     def __init__(self, x, y): self.x, self.y = x, y
//     def __add__(self, other): return Vector(self.x + other.x, self.y + other.y)
//     def __eq__(self, other):  return (self.x, self.y) == (other.x, other.y)
// Vector(1, 2) + Vector(3, 4) == Vector(4, 6)   -> True

Overloading is not overriding

Overloading: same name, different parameters, chosen at compile time, usually in one class. Overriding: same signature, in a subclass, chosen at run time. Mixing them up is the most common viva question slip.

Quick check: Which pair of Java methods is a valid overload?

  • int total(int a) and double total(int a)
  • void run() and private void run()
  • void log(String s) and void log(String s, int level)
  • static void x() and void x()
Answer

void log(String s) and void log(String s, int level) — Overloads must differ in their parameter lists; return type or modifiers alone are not enough.