Introduction
Hey Folks! 👋
Good Day...
Today’s Java session was one of those classes where multiple concepts suddenly connected together. Initially, I thought Method Overriding was just about writing the same method in a child class. But as we explored deeper, I understood how concepts like Upcasting, Runtime Polymorphism, Dynamic Method Dispatch, Reference Types, and Object Types all work together behind the scenes.
In this blog, I’ll share my key takeaways from today's session and the thought process that helped me understand them.
1. A Class is the Data Type of an Object
One of the first things I learned today was that a class acts as a data type for objects.
For example:
Dog dog = new Dog();
Here:
-
Dogis the class -
dogis the reference variable -
new Dog()creates the object
Just like int is a data type for numbers, a class becomes a data type for objects.
2. Defining a Child Object as a Parent Reference
The next interesting concept was:
Animal animal = new Dog();
At first, this syntax looked strange.
Questions that came to my mind:
- Why are we creating a Dog object?
- Why is the reference variable Animal?
- Is Java allowing this?
The answer is yes.
This concept is called Upcasting.
Since every Dog is an Animal, Java automatically allows a child object to be stored inside a parent reference.
Dog → Animal
This conversion happens automatically and is therefore known as Implicit Upcasting.
3. What is Method Overriding?
Method Overriding happens when a child class provides its own implementation of a method already present in the parent class.
Example:
class Animal {
void makeSound() {
System.out.println("Animal Sound");
}
}
class Dog extends Animal {
@Override
void makeSound() {
System.out.println("Bark");
}
}
Here, the Dog class overrides the makeSound() method of the Animal class.
4. Rules of Method Overriding
One important thing I learned today is that overriding follows strict rules.
The following must remain the same:
Method Name
Number of Parameters
Parameter Data Types
Parameter Order
Example:
void display(String name, int age)
The child class must use the exact same method signature.
5. What About Return Types?
Initially, I assumed return types must always be identical.
That is partially true.
Example:
String getName()
can be overridden by:
String getName()
However, Java also supports something called Covariant Return Types.
Example:
class Animal {
Animal getAnimal() {
return new Animal();
}
}
class Dog extends Animal {
@Override
Dog getAnimal() {
return new Dog();
}
}
Since Dog is a subclass of Animal, Java allows this override.
6. Why Do We Call Method Overriding Runtime Polymorphism?
This was the most important learning of the session.
Consider:
Animal animal = new Dog();
animal.makeSound();
The compiler only knows:
Animal animal
But the actual object created is:
new Dog()
When the method executes, Java checks the actual object type and calls:
Dog.makeSound()
instead of:
Animal.makeSound()
The method decision happens while the program is running.
That is why it is called Runtime Polymorphism.
7. Reference Type vs Object Type
This concept helped me understand Runtime Polymorphism more clearly.
Example:
Animal animal = new Dog();
Reference Type:
Animal
Object Type:
Dog
Important Rule
Reference Type decides:
Which methods are visible at compile time
Object Type decides:
Which overridden method runs at runtime
This single statement clarified many of my doubts.
8. Dynamic Method Dispatch
When Java executes:
animal.makeSound();
it performs a runtime check.
Java asks:
What object is this reference pointing to?
If the object is Dog:
Dog.makeSound()
is executed.
If the object is Cat:
Cat.makeSound()
is executed.
This mechanism is known as Dynamic Method Dispatch.
9. Why Is It Called Runtime Polymorphism?
Another interesting discussion today was:
Why specifically "Runtime"?
Because objects are created only when the application runs.
Example:
new Dog()
The object memory is allocated during execution.
Since Java determines the actual method implementation using the runtime object, the behavior can only be finalized while the program is running.
Hence the name:
Runtime Polymorphism
10. Practice Exercise
To reinforce these concepts, I implemented an Employee hierarchy.
Employee e1 = new Developer();
Employee e2 = new Tester();
e1.work();
e2.work();
This simple example helped me visualize:
- Upcasting
- Method Overriding
- Dynamic Method Dispatch
- Runtime Polymorphism
all working together in a single program.
Final Thoughts
Today's session completely changed how I view Method Overriding.
Initially, I thought overriding was just about writing the same method in a child class.
Now I understand that Method Overriding is the foundation of:
- Runtime Polymorphism
- Dynamic Method Dispatch
- Upcasting
- Flexible Object-Oriented Design
The biggest takeaway for me was:
Reference Type decides what methods can be called. Object Type decides which overridden method gets executed.
That one sentence connected almost every concept we discussed today.
Top comments (0)