Polymorphism
Polymorphism is a fancy word that means "many forms." In Java, it means a variable of a parent type can hold an object of any child type, and Java will call the RIGHT method automatically
class Criminal {
String name;
Criminal(String name) { this.name = name; }
void speak() { System.out.println("..."); }
}
class Driver extends Criminal {
Driver(String name) { super(name); }
@Override
void speak() { System.out.println("I'm the driver " + name); }
}
class Gunman extends Criminal {
Gunman(String name) { super(name); }
@Override
void speak() { System.out.println("I'm the gunman " + name); }
}
public class Main {
public static void main(String[] args) {
Criminal c = new Driver("Tommy"); // parent type, child object
c.speak(); // prints "I'm the driver Tommy" not "..."
}
}
Even though c is declared as Criminal, Java knows it's actually a Driver at runtime and calls Driver's speak(). This is called dynamic dispatch: Java dispatches the method call to the actual object type, not the declared type
This gets REALLY powerful with arrays and loops. Think about Vice City: you have different types of criminals, all extending the base Criminal class. You can store them all in ONE array
class Criminal {
String name;
Criminal(String name) { this.name = name; }
void speak() { System.out.println("..."); }
}
class Driver extends Criminal {
Driver(String name) { super(name); }
@Override
void speak() { System.out.println("I'm the driver " + name); }
}
class Gunman extends Criminal {
Gunman(String name) { super(name); }
@Override
void speak() { System.out.println("I'm the gunman " + name); }
}
public class Main {
public static void main(String[] args) {
Criminal[] crew = { new Driver("Tommy"), new Gunman("Lance") };
for (Criminal c : crew) {
c.speak();
}
}
}
Output
I'm the driver Tommy
I'm the gunman Lance
We never checked "is this a driver or a gunman?" Java figured it out for us. The loop just calls c.speak() and Java routes it to the correct override. That's polymorphism in action
Sometimes you need to check what type an object actually is. Java has the instanceof keyword for that
public class Main {
public static void main(String[] args) {
Criminal c = new Driver("Tommy");
if (c instanceof Driver) {
System.out.println("It's a driver!");
}
}
}
This is useful when you need to access child-specific methods. But in general, if you're using instanceof a lot, you might be fighting against polymorphism instead of using it. The whole point is to NOT care about the specific type
Here's why this matters in real code. Imagine a method that takes any Criminal
public class Main {
static void present(Criminal c) {
c.speak();
}
}
You can pass a Driver, a Gunman, a Boss, anything that extends Criminal. The method doesn't need to know or care. That's the power. One method handles ALL criminals, current and future
Like Cortez in Vice City: he gives missions to Tommy, Lance, whoever. He doesn't care about the specific person, just that they can do the job. The "job" is the method signature, and polymorphism makes sure the right person does it their way
Mission: Gang Roll Call
Tommy calls his crew for a roll call. Each member answers their own way, but you want a single loop that makes them all speak, without checking what type each one is.
Create the Criminal, Driver, and Gunman classes (Criminal has speak() printing "..."; Driver overrides with "I'm the driver " + name; Gunman overrides with "I'm the gunman " + name).
In main, store the two names in variables name1 and name2 (start with "Tommy" and "Lance"). Create a Criminal[] array containing a Driver from name1 and a Gunman from name2. Loop through the array and call speak() on each.
Example
I'm the driver Tommy
I'm the gunman Lance