Initiative: To implement runtime polymorphism (Dynamic Method Dispatch) using an abstract base.
abstract class Shape { // Abstract base class that cannot be instantiated directly
protected String type; // Attribute to store the name/type of the shape
public Shape(String type) { // Constructor for the abstract Shape class
this.type = type; // Initialize the shape type string
} // End of constructor
public abstract double area(); // Abstract method with no body; children MUST implement this
public void display() { // Concrete method in an abstract class for shared behavior
System.out.println("Shape: " + type + " | Area: " + area()); // Print type and calculated area
} // End of display method
} // End of abstract Shape class
class Circle extends Shape { // Concrete class representing a Circle
private double radius; // Private attribute for the circle's radius
public Circle(double r) { // Constructor accepting a radius value
super("Circle"); // Pass type string to the Shape parent constructor
this.radius = r; // Initialize the radius attribute locally
} // End of Circle constructor
@Override // Explicitly indicate overriding the abstract area method
public double area() { // Implementation of area calculation for a circle
return Math.PI * radius * radius; // Return result using PI and radius squared
} // End of area implementation
} // End of Circle class
class Rectangle extends Shape { // Concrete class representing a Rectangle
private double w, h; // Private attributes for width and height
public Rectangle(double w, double h) { // Constructor accepting width and height
super("Rectangle"); // Pass type string to the Shape parent constructor
this.w = w; // Initialize width attribute
this.h = h; // Initialize height attribute
} // End of Rectangle constructor
@Override // Explicitly indicate overriding the abstract area method
public double area() { // Implementation of area calculation for a rectangle
return w * h; // Return result of multiplying width by height
} // End of area implementation
} // End of Rectangle class
public class PolymorphismLab { // Main class to demonstrate dynamic method dispatch
public static void main(String[] args) { // Program entry point
System.out.println("--- Dynamic Method Dispatch Lab ---"); // Print lab header
Shape[] shapes = new Shape[2]; // Create an array of abstract Shape references
shapes[0] = new Circle(5.0); // Store a Circle object in the first reference slot
shapes[1] = new Rectangle(4.0, 6.0); // Store a Rectangle object in the second slot
for (Shape s : shapes) { // Iterate through the array using a parent reference
s.display(); // Call display; Java resolves the correct 'area()' at runtime
} // End of polymorphic loop
System.out.println("Lab Finished."); // Final log for the polymorphism demo
} // End of main method
} // End of PolymorphismLab class