Method Overriding

Method Overriding

A school program needs reliable data and clear rules. An overriding method supplies subclass behavior for an inherited instance-method contract. The actual object determines which implementation runs.

  1. Understand

    An overriding method supplies subclass behavior for an inherited instance-method contract.

  2. Apply

    Trace the Java example, predict its output and explain the result before running it.

  3. Avoid mistakes

    Static methods are hidden, not dynamically overridden. The override must match the inherited signature and compatible return type.

Method Overriding

Method Overriding allows a subclass to provide a specific implementation of a method that is already defined in its superclass. This enables dynamic behavior and helps in achieving runtime polymorphism.

Why Do We Override Methods?

Imagine you’re building a system where the parent class defines a generic action — like makeSound() — but the child classes need to provide their own unique version of this behavior. That’s where method overriding shines. It lets subclasses tailor inherited behavior to fit their specific needs.

Rules for Method Overriding

  • The method must have the same name, return type, and parameter list as the method in the parent class.
  • The method in the child class must be accessible and not more restrictive than the one in the parent class.
  • Only inherited methods can be overridden (not constructors or private methods).
  • @Override annotation is optional but highly recommended for clarity and error detection.

Simple Example of Method Overriding

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

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

public class Main {
    public static void main(String[] args) {
        Animal myDog = new Dog();
        myDog.makeSound();  // Which method runs?
    }
}
Dog barks

Explanation

Even though myDog is declared as type Animal, the makeSound() method of the Dog class is invoked. This is because of runtime polymorphism — Java determines the method to call based on the actual object type at runtime, not the reference type.

Using @Override Annotation

The @Override annotation tells the compiler that we intend to override a method. If the method signature doesn't exactly match, the compiler throws an error. This helps catch typos and logic bugs early.

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

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

Calling Superclass Method Inside Overridden Method

Sometimes, we want to extend the functionality of the superclass method rather than completely replacing it. We can do that using super.methodName().

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

class Car extends Vehicle {
    @Override
    void start() {
        super.start(); // Call the superclass method
        System.out.println("Car is starting");
    }
}

public class Main {
    public static void main(String[] args) {
        Vehicle v = new Car();
        v.start();
    }
}
Vehicle is starting
Car is starting

Final Methods Cannot Be Overridden

If a method is declared with the final keyword in the parent class, it cannot be overridden by any subclass. Attempting to do so will result in a compile-time error.

class Shape {
    final void draw() {
        System.out.println("Drawing Shape");
    }
}

class Circle extends Shape {
    // Compilation error
    void draw() {
        System.out.println("Drawing Circle");
    }
}

Overriding vs Overloading

Feature Method Overriding Method Overloading
Definition Redefining a method of the parent class in the child class Defining multiple methods in the same class with the same name but different parameters
Inheritance Requires inheritance No inheritance required
Runtime/Compile-time Runtime polymorphism Compile-time polymorphism

Real-World Use Case

Suppose you're creating a payment system. You define a generic processPayment() method in the superclass. Credit cards, UPI, and net banking can each override this method to implement their specific logic.

class Payment {
    void processPayment() {
        System.out.println("Processing generic payment");
    }
}

class CreditCardPayment extends Payment {
    @Override
    void processPayment() {
        System.out.println("Processing credit card payment");
    }
}

Key Takeaways

  • Overriding allows dynamic method resolution during runtime.
  • The method signature must match exactly with the superclass method.
  • Use @Override to avoid unintentional mistakes.
  • Polymorphism is made possible by method overriding.

Important boundaries and mistakes

Static methods are hidden, not dynamically overridden. The override must match the inherited signature and compatible return type.

Try the school example

Before running this Java program, write down each line you expect to see. Identify the value, branch, object or exception responsible for each line. Then explain whether the following assumption is valid: Static methods are hidden, not dynamically overridden.

Java 17 · Main.java · complete practice program

public class Main  {
  static abstract class Person  {
    abstract String role();
  }
  static class Teacher extends Person  {
    @Override String role()  {
      return "Teacher";
    }
  }
  public static void main(String[] args)  {
    Person p = new Teacher();
    System.out.println(p.role());
  }
}

Worked answer and reasoning

Java 17 · Main.java · source repeated for this answer

public class Main  {
  static abstract class Person  {
    abstract String role();
  }
  static class Teacher extends Person  {
    @Override String role()  {
      return "Teacher";
    }
  }
  public static void main(String[] args)  {
    Person p = new Teacher();
    System.out.println(p.role());
  }
}

Expected output

Teacher

An overriding method supplies subclass behavior for an inherited instance-method contract. The actual object determines which implementation runs.

Static methods are hidden, not dynamically overridden. The override must match the inherited signature and compatible return type.

Run with javac Main.java, then java Main. The declaration inside Main keeps the helper type available to this standalone example.

Check your understanding

For the complete practice program in this lesson, which output is expected on Java 17?
Choose one answer. You can try again.

Answer and explanation

Teacher

An overriding method supplies subclass behavior for an inherited instance-method contract. The actual object determines which implementation runs. Static methods are hidden, not dynamically overridden. The override must match the inherited signature and compatible return type.

Check a common mistake

For Person p = new Teacher(), which role implementation runs?
Choose one answer. You can try again.

Answer and explanation

Teacher’s overriding instance method.

Runtime dispatch follows the actual object for overridden instance methods. File order is irrelevant; the declared type still controls which members are accessible.

What to remember

An overriding method supplies subclass behavior for an inherited instance-method contract. The actual object determines which implementation runs. Static methods are hidden, not dynamically overridden. The override must match the inherited signature and compatible return type.

Related explanations: Java Variables, Java If Statement - Syntax and Examples, Java Class - Blueprint of Objects, Exceptions in Java Introduction.

Supporting documentation: Official Java learning guide and Java 17 language specification.

Reaching the recap and completing the quizzes are separate milestones.

    Next lesson: Abstraction →