Page Content

Tutorials

Method Overriding In C#: Behaviour Growth in Derived Classes

Method Overriding in C#

In object-oriented programming (OOP), method overriding is a basic idea that enables a derived class to offer a particular implementation for a method that is already specified in its base (parent) class. This procedure is also known as late binding or run-time polymorphism since it chooses which method implementation to employ based on the object’s actual type at run-time.

Key Concepts of Method Overriding

Purpose

In a subclass, method overriding is used to modify or specialise the behaviour of an inherited method. This allows for versatile and adaptable software architectures by letting objects of different classes to react to the same method call in different ways. If the implementation of the base class is not called, the derived class must make sure that its behaviour is consistent with that of the base class.

Keywords

To override a method in C#, use the virtual and override keywords.

virtual: To indicate that derived classes can override a method, the virtual modifier must be explicitly specified with the base class method. C# differs significantly from languages like Java in that its methods are not by default virtual. One cannot designate a virtual method as private.

override: With the override modifier, the derived class’s method that re-implements the base class’s virtual method needs to be explicitly specified. The overriding method must have the same signature as the base class virtual method, including the same name and parameter list. In the child class, overriding the method is not required.

new Keyword (Method Hiding)

Method concealing, commonly known as shadowing, is supported in C# using the new keyword. A derived class method that hides the base class method is created when it employs the new keyword that has the same name as a base class method, whether or not it is virtual. The method call is resolved using the static type of the object reference rather than its actual runtime type in this instance, preventing polymorphic behaviour. For a method with the same name in a derived class, the compiler will raise an error and the method will act as though new were present if neither override nor new is supplied.

Polymorphic Behavior

The Common Language Runtime (CLR) makes sure that, even when an object is referenced by a base class type, the right method implementation (from the most derived class) is called at runtime when a method is overridden. This is a fundamental feature of polymorphism.

Calling Base Implementation

Even in an overriding method, you can use the base keyword to invoke the method’s implementation from the base class. Because of this, the derived class might enhance or supplement the original functionality instead of totally replacing it.

Abstract Methods

Non-abstract derived classes must use the override modifier to override abstract methods, which are declared in abstract classes but lack an implementation. Methods that are abstract are implicitly virtual.

Sealed Methods

In a derived class, an overridden method can be marked as sealed to stop it from being overridden in any more derived classes.

Differences from Method Overloading

Differentiating between method overloading and overriding is crucial:

Method Overloading: It is the process of defining several methods with the same name but distinct signatures (i.e., different numbers, types, or parameter order) within the same class (or across an inheritance tree). Different approaches to completing a same work are provided by overloading. Static (compile-time) polymorphism is what it is.

Method Overriding: Entails re-implementing a method in a derived class using the same name and signature as their base class counterpart. The method’s behaviour for the derived class is altered via overriding. It’s a type of run-time, dynamic polymorphism.

FeatureMethod OverloadingMethod Overriding
SignatureSame name, different signatureSame name, same signature
LocationWithin the same class or across parent/child classesOnly in a child class
Keywords UsedNo separate keywordsvirtual (base), override (derived)
Polymorphism TypeStatic (Compile-time)Dynamic (Run-time)
PurposeProvide multiple behaviors for a methodChange/replace the behavior of a method
Parent PermissionNot requiredExplicit permission (virtual) from parent required

Code Example of Method Overriding

This sample illustrates polymorphism behaviour and shows how to use virtual and override keywords to override methods:

using System;
// Base class
public class Vehicle
{
    protected int NumberOfWheels { get; set; } = 0;
    public Vehicle() { }
    // Declare the method as virtual to allow overriding in derived classes
    public virtual void Display()
    {
        Console.WriteLine($"The number of wheels for the {nameof(Vehicle)} is {NumberOfWheels}");
    }
}
// Derived class 1
public class Ducati : Vehicle
{
    public Ducati()
    {
        NumberOfWheels = 2;
    }
    // Override the Display method to provide specific implementation for Ducati
    public override void Display()
    {
        Console.WriteLine($"The number of wheels for the {nameof(Ducati)} is {NumberOfWheels}");
    }
}
// Derived class 2
public class Lamborghini : Vehicle
{
    public Lamborghini()
    {
        NumberOfWheels = 4;
    }
    // Override the Display method for Lamborghini
    public override void Display()
    {
        Console.WriteLine($"The number of wheels for the {nameof(Lamborghini)} is {NumberOfWheels}");
        // Optionally, call the base class implementation using 'base' keyword
        // Console.Write(" (Base class info: ");
        // base.Display();
        // Console.WriteLine(")");
    }
}
public class TestPolymorphism
{
    public static void Main(string[] args)
    {
        Vehicle vehicle; // Declare a base class reference
        // Assign an instance of the base class to the base class reference
        vehicle = new Vehicle();
        vehicle.Display();
        Console.WriteLine("----------");
        // Assign an instance of a derived class (Ducati) to the base class reference
        vehicle = new Ducati();
        vehicle.Display();
        Console.WriteLine("----------");
        // Assign another instance of a derived class (Lamborghini) to the base class reference
        vehicle = new Lamborghini();
        vehicle.Display();
        Console.WriteLine("----------");
        // Example using an array of base class type to demonstrate polymorphism
        // Correctly initialize the array with a size that can hold the vehicles
        Vehicle[] garage = new Vehicle[3]; // Array to hold 3 vehicles
        // Assign instances to valid indices within the array
        garage[0] = new Vehicle();
        garage[1] = new Ducati();
        garage[2] = new Lamborghini();
        Console.WriteLine("\nGarage vehicles:");
        foreach (Vehicle v in garage)
        {
            v.Display(); // At runtime, the correct overridden method is invoked for each object
        }
    }
}

Output

The number of wheels for the Vehicle is 0
----------
The number of wheels for the Ducati is 2
----------
The number of wheels for the Lamborghini is 4
----------
Garage vehicles:
The number of wheels for the Vehicle is 0
The number of wheels for the Ducati is 2
The number of wheels for the Lamborghini is 4

You can alo read C# Destructor: Your Guide To The Resource Management

Agarapu Geetha
Agarapu Geetha
My name is Agarapu Geetha, a B.Com graduate with a strong passion for technology and innovation. I work as a content writer at Govindhtech, where I dedicate myself to exploring and publishing the latest updates in the world of tech.
Index