The Power of Polymorphism in Java: Late Binding and Upcasting
Have you ever wondered how Java handles method calls when dealing with subclasses and superclasses? Let’s dive into the concept of late binding and upcasting to understand the magic of subtype polymorphism in action.
Imagine a scenario where a superclass Shape
declares a method draw()
, and its subclass Circle
overrides this method. Now, when you instantiate an object like Shape s = new Circle();
and call s.draw();
, which draw()
method gets executed? The compiler may seem clueless at first glance, but it actually sets the stage for late binding.
To illustrate this concept in action, I’ve crafted a Java application showcasing subtype polymorphism through upcasting and late binding. This application introduces classes like Shape
, Circle
, Rectangle
, and Shapes
, each housed in their individual source files. Below is a snippet of the hierarchy defined in Listing 1.
Listing 1. Declaring a hierarchy of shapes
class Shape
{
void draw()
{
}
}
class Circle extends Shape
{
private int x, y, r;
Circle(int x, int y, int r)
{
this.x = x;
this.y = y;
this.r = r;
}
@Override
void draw()
{
System.out.println("Drawing circle (" + x + ", "+ y + ", " + r + ")");
}
}
class Rectangle extends Shape
{
private int x, y, w, h;
Rectangle(int x, int y, int w, int h)
{
this.x = x;
this.y = y;
this.w = w;
this.h = h;
}
@Override
void draw()
{
System.out.println("Drawing rectangle (" + x + ", "+ y + ", " + w + "," +
h + ")");
}
}
Listing 2 showcases the main application class Shapes
, where the main()
method plays a pivotal role in orchestrating this demonstration of polymorphism. Embrace the power of late binding and upcasting in Java programming and witness how dynamic method resolution transforms the way we approach object-oriented design!