Java Method Overriding: Learn Runtime Polymorphism with Examples

0

Inheritance allows a child class to reuse behavior from its parent, but reuse does not mean the child must accept that behavior exactly as it is. Sometimes a child class needs to provide a more specific implementation of a method inherited from its parent. This is where method overriding becomes important.

Method overriding occurs when a child class provides its own implementation of an inherited instance method while keeping the same method signature as the parent method.

Method overriding allows a child class to redefine inherited behavior so that it can respond according to its own specific requirements.

Why Does Method Overriding Exist?

A parent class usually represents general behavior, while child classes represent more specific types. A general Animal can have a sound() method, but a dog and a cat do not make the same sound.

Instead of creating unrelated methods such as dogSound() and catSound(), the child classes can override the common sound() method.

A Simple Example

class Animal {
    void sound() {
        System.out.println("Animal makes a sound");
    }
}

class Dog extends Animal {
    @Override
    void sound() {
        System.out.println("Dog barks");
    }
}

The Dog class inherits sound() from Animal, but it replaces the inherited implementation with behavior appropriate for a dog.

Dog dog = new Dog();
dog.sound();

The output is:

Dog barks

The @Override Annotation

Java provides the @Override annotation to clearly indicate that a method is intended to override a method from a superclass.

class Vehicle {
    void start() {
        System.out.println("Vehicle starts");
    }
}

class Car extends Vehicle {
    @Override
    void start() {
        System.out.println("Car starts with a key");
    }
}

The annotation is not what creates overriding. The method signature and inheritance relationship establish the override. The annotation tells the compiler and other developers that overriding is intentional.

Use @Override whenever you intentionally override an inherited method. It helps the compiler catch mistakes such as incorrect method signatures.

Why @Override Is Valuable

Imagine you accidentally change the method name while intending to override it.

class Animal {
    void sound() {
        System.out.println("Animal sound");
    }
}

class Dog extends Animal {
    @Override
    void sounds() {
        System.out.println("Dog barks");
    }
}

Because sounds() does not correctly override sound(), the compiler reports an error. Without @Override, you might accidentally create a new method and not realize that the original method was never overridden.

Rules for Method Overriding

Java places specific rules around overriding. Understanding them prevents many compilation errors and interview mistakes.

Rule Requirement
Inheritance The child class must inherit from the parent class.
Method signature The overriding method must have the same name and parameter list.
Return type The return type must be the same or covariant.
Access level The overriding method cannot reduce the accessibility of the parent method.
Static methods Static methods are hidden, not overridden.
Final methods A final method cannot be overridden.
Private methods Private methods are not inherited and therefore cannot be overridden.

Same Method Signature

The child method must match the parent's method name and parameter list.

class Parent {
    void display(int value) {
        System.out.println(value);
    }
}

class Child extends Parent {
    @Override
    void display(int value) {
        System.out.println("Child: " + value);
    }
}

If the parameter list changes, the method may become an overloaded method rather than an overridden method.

Overriding vs Overloading

These two concepts are frequently confused because both involve methods with the same name. The important difference is whether the relationship happens across inheritance and whether the parameter list changes.

Feature Overriding Overloading
Inheritance required Yes No
Method name Same Same
Parameter list Same Different
Main purpose Specialize inherited behavior Provide multiple ways to call a method
Binding Primarily runtime Compile time

Runtime Method Selection

One of the most important reasons overriding matters is that Java can select the appropriate overridden method at runtime based on the actual object.

class Animal {
    void sound() {
        System.out.println("Animal sound");
    }
}

class Dog extends Animal {
    @Override
    void sound() {
        System.out.println("Dog barks");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal animal = new Dog();

        animal.sound();
    }
}

Although the reference type is Animal, the actual object is a Dog. Therefore, Java executes the overridden Dog.sound() method.

For overridden instance methods, Java uses the actual object type at runtime to determine which implementation executes.

Calling the Parent Implementation with super

Sometimes the child does not want to completely replace the parent's behavior. Instead, it wants to perform the parent's work and then add something extra.

class Vehicle {
    void start() {
        System.out.println("Vehicle system starts");
    }
}

class Car extends Vehicle {
    @Override
    void start() {
        super.start();
        System.out.println("Car engine starts");
    }
}

The super.start() call invokes the parent implementation before the child adds its specialized behavior.

Can Static Methods Be Overridden?

No. Static methods belong to the class rather than individual objects, so they are not overridden in the same way as instance methods. If a child declares a static method with the same signature, the method is considered hidden.

class Parent {
    static void show() {
        System.out.println("Parent");
    }
}

class Child extends Parent {
    static void show() {
        System.out.println("Child");
    }
}

This is method hiding, not runtime method overriding. That distinction is a common interview question.

Can final Methods Be Overridden?

No. A method declared with the final keyword cannot be overridden by a child class.

class Parent {
    final void display() {
        System.out.println("Fixed behavior");
    }
}

class Child extends Parent {
    // Cannot override display()
}

The final keyword tells Java that the method's implementation must not be replaced by subclasses.

Access Modifier Rule

An overriding method cannot be less accessible than the method it overrides. For example, a public parent method cannot be overridden with a protected or private method.

class Parent {
    public void display() {
        System.out.println("Parent");
    }
}

class Child extends Parent {
    @Override
    public void display() {
        System.out.println("Child");
    }
}

The child can keep the same access level or make the method more accessible, but it cannot narrow access.

Common Beginner Mistakes

  • Changing the parameter list and assuming the method is overridden.
  • Forgetting to use @Override and accidentally creating a different method.
  • Trying to override a private, static, or final method.
  • Reducing the access level of an overridden method.
  • Assuming the reference type always determines which overridden method executes.

Best Practice

Use @Override consistently. It documents your intention and lets the compiler verify that the method actually overrides a parent method.

Also, keep overridden methods behaviorally consistent with the parent contract. A child should specialize its parent's behavior rather than unexpectedly violating what users of the parent type reasonably expect.

Interview Insight

A strong interview answer is: "Method overriding occurs when a subclass provides its own implementation of an inherited instance method with the same signature. It enables runtime polymorphism, and Java recommends using the @Override annotation to verify the intended override."

Final Takeaway

Method overriding is where inheritance becomes genuinely dynamic. A parent class can define general behavior, while each child can specialize that behavior without changing the common method name. Remember the core rules: inheritance must exist, the method signature must match, access cannot be reduced, and final, private, and static methods do not participate in ordinary overriding. This foundation will make the next topic, constructor inheritance, much easier to understand because constructors follow very different rules from methods.

Post a Comment

0Comments
Post a Comment (0)