Overriding

Comprehensive study notes, diagrams, and exam preparation for Overriding.

Overriding

Definition

Overriding is the process in which a subclass redefines a method inherited from its superclass using the same method name, same parameter list, and compatible return type, so that the subclass version is executed instead of the superclass version when the method is called on a subclass object.

In simple terms, overriding means replacing the inherited behavior with a new behavior in the child class.


Main Content

1. Method Overriding

  • Method overriding occurs when a subclass provides its own implementation of a method that is already present in the parent class.
  • The overridden method must generally have the same name, same number and type of parameters, and a compatible return type, so that the method signature remains consistent.

Example:

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

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

Here, Dog overrides the sound() method of Animal. When sound() is called on a Dog object, the output is Dog barks.

Key idea:

  • The superclass method already exists.
  • The subclass changes the behavior for its own specific purpose.

2. Runtime Polymorphism

  • Overriding is closely related to runtime polymorphism, also called dynamic method dispatch.
  • The method that gets executed is decided at runtime based on the actual object type, not the reference type.

Example:

Animal a = new Dog();
a.sound();

Even though the reference type is Animal, the actual object is Dog, so the overridden sound() method in Dog is executed.

Why this matters:

  • It allows one reference type to represent many object forms.
  • It improves code flexibility and extensibility.
  • It supports writing generic code that can work with different subclasses.

Simple view:

Animal reference  --->  Dog object
a.sound() calls Dog's version

3. Rules and Restrictions of Overriding

  • The method name and parameter list must remain the same; changing parameters creates overloading, not overriding.
  • The return type should be the same or a subtype in languages that support covariant return types.
  • Access level cannot be more restrictive than the overridden method; for example, a public method in the parent cannot be overridden as private.
  • Final methods, static methods, and constructors are generally not overridden in the same way as instance methods.
  • The overriding method may throw fewer or narrower checked exceptions than the parent method, depending on the language rules.

Important distinction:

  • Overriding happens with inheritance.
  • The child class must already extend or inherit the parent class.
  • The child method replaces inherited behavior, but only for instance methods in typical object-oriented usage.

Example of correct overriding:

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

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

Example of not overriding:

class Car extends Vehicle {
    void start(int keyType) {
        System.out.println("Car starts differently");
    }
}

The second example is method overloading because the parameter list changed.


Working / Process

  1. A superclass defines a method with a general behavior.
  2. A subclass inherits that method and then provides its own implementation with the same signature.
  3. When the method is called using an object, the runtime system checks the actual object type and executes the subclass version if it has overridden the method.

Example process:

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

class Circle extends Shape {
    void draw() {
        System.out.println("Drawing a circle");
    }
}

public class Test {
    public static void main(String[] args) {
        Shape s = new Circle();
        s.draw();
    }
}

How it works:

  • Shape defines draw().
  • Circle overrides draw().
  • s is a reference of type Shape, but it points to a Circle object.
  • At runtime, Circle's draw() runs.

Flow of execution:

Reference type: Shape
Actual object: Circle
Method call: draw()
Executed method: Circle.draw()

This process is the foundation of dynamic behavior in object-oriented programming.


Advantages / Applications

  • It enables code reusability because the parent class provides a common structure while subclasses adjust specific behavior.
  • It supports polymorphism, allowing one interface or superclass reference to work with many different object types.
  • It improves maintainability and extensibility, because new subclasses can be added with specialized behavior without changing existing code.

Applications:

  • In GUI programming, different components can override rendering methods.
  • In game development, different characters can override movement or attack methods.
  • In business systems, specialized employee or account classes can override calculation methods such as salary, interest, or tax computation.

Example application:

class Account {
    double getInterest() {
        return 0.0;
    }
}

class SavingsAccount extends Account {
    double getInterest() {
        return 5.0;
    }
}

A general account model can be extended, while each account type gives its own result.


Summary

  • Overriding is a way for a subclass to replace a parent class method with its own version.
  • It is used to provide class-specific behavior while keeping the same method structure.
  • It is important for runtime polymorphism and flexible inheritance-based design.
  • Important terms to remember: superclass, subclass, method signature, runtime polymorphism, dynamic method dispatch