Unit 4: Object-Oriented Programming
Polymorphism, from the Greek for "many forms," is an OOP principle that allows you to treat objects of different classes as if they were objects of a common superclass. It's the key to writing flexible and extensible robot code.
Polymorphism builds directly on inheritance and method overriding. It allows you to write code that works with a general type (like `Mechanism`) but have it automatically execute the specific, overridden behavior of a subtype (like `Intake` or `Shooter`).
This is the magic behind polymorphism. When you call a method on an object, the Java Virtual Machine (JVM) checks the actual type of the object at runtime to decide which version of the method to run, not the type of the reference variable.
Let's define a general `Mechanism` superclass with an `activate()` method. Then we'll create two specific subclasses, `Intake` and `Shooter`, that each provide their own unique implementation of `activate()`.
// 1. The Superclass
public class Mechanism {
public void activate() {
System.out.println("A generic mechanism is activating.");
}
}
// 2. A Subclass
public class Intake extends Mechanism {
@Override
public void activate() {
System.out.println("Intake rollers are spinning to pick up a note.");
}
}
// 3. Another Subclass
public class Shooter extends Mechanism {
@Override
public void activate() {
System.out.println("Shooter flywheel is spinning up to speed.");
}
}
Now, we can create an array of `Mechanism` references but store different subclass objects in it. When we loop through and call `activate()` on each one, the JVM will dynamically dispatch the correct, overridden method.
// Create an array of the SUPERCLASS type
Mechanism[] robotMechanisms = new Mechanism[3];
// Store objects of the SUBCLASS types in the array (this is "upcasting")
robotMechanisms[0] = new Intake();
robotMechanisms[1] = new Shooter();
robotMechanisms[2] = new Intake();
// Loop through and call the same method on each object
for (Mechanism mech : robotMechanisms) {
mech.activate(); // Polymorphism! The correct method is called at runtime.
}
// --- EXPECTED OUTPUT ---
// Intake rollers are spinning to pick up a note.
// Shooter flywheel is spinning up to speed.
// Intake rollers are spinning to pick up a note.
This approach allows you to write incredibly flexible code. You can write a method that accepts a generic `Mechanism` object, and that same method will work correctly with an `Intake`, a `Shooter`, or any other `Mechanism` subclass you create in the future, without needing any changes.
Question: Given the code `Mechanism myMechanism = new Shooter();`, which `activate()` method will be called when `myMechanism.activate()` is executed?