Card image cap

Using abstract, virtual, override and new keywords under method Overriding context

C# Fundamentals  • Posted 6 months ago

Overriding is way in which a child type method can extend its base type implementation, which is also one of the core features of Inheritance in any Object Oriented Programming paradigm. Let's talk about the various ways of influencing compiler decisions over overriding method implementations under a base-derived relationships using a few keywords in C#.

Scenario 1 - virtual and override:

Consider the below definition of a base Animal type which defines a single method Sound() that has a little behaviour for itself.


namespace WorkConsoleApp
{
    public class Animal
    {
        public void Sound()
        {
            Console.WriteLine("Animal makes Sound");
        }
    }
}

Now consider a derived type Cat which extends the base Animal type, with its own implementation as:


namespace WorkConsoleApp
{
    public class Cat : Animal
    {
        public void Sound()
        {
            // extending the base implementation
            // by calling the base method
            // base.Sound();
            Console.WriteLine("Cat makes Sound");
        }
    }
}

Now when we create instances for these types in our Main() method as below:


namespace WorkConsoleApp
{
    public class NewProgram 
    {
        public static void Main(string[] args) 
        {
            // assign derived object
            // to base reference
            Animal a = new Cat();
            a.Sound();

            // create instance of
            // derived method directly
            Cat c = new Cat();
            c.Sound();
        }
    }
}

Here we declare a variable animal which is of type Animal and have assigned it to a new instance of type Cat. And we call the method animal.Sound() on that variable. Next we declare a variable of type Cat which is assigned to a new instance of Cat and call method cat.Sound(). When we run this program:


BaseDerived.cs(20,21): warning CS0108: 'Cat.Sound()' hides inherited member 'Animal.Sound()'. 
Use the new keyword if hiding was intended.
Animal makes Sound (from a.Sound())
Cat makes Sound (from c.Sound())

We see that we get the display statements "Animal makes Sound" (which is from the Animal type) and "Cat makes Sound" (which is from the Cat type). This is because in C# we have precendence on the left hand side which is variable animal of type Animal in this case. And hence we get the method Animal.Sound() called even though we pass an instance of the derived type which is Cat to the variable.

What's more important is that we get a compile time warning message about the similarity of the method signatures we have in both the base type and the derived type.

Now how do I earmark the base method such that we are to override its implementation? I'd simply mark the base method as virtual, as below:


    public class Animal
    {
        public virtual void Sound()
        {
            Console.WriteLine("Animal makes Sound");
        }
    }

Now when I run the program again, the compiler warning changes as:


BaseDerived.cs(20,21): warning CS0114: 'Cat.Sound()' hides inherited member 'Animal.Sound()'. 
To make the current member override that implementation, add the override keyword. 
Otherwise add the new keyword.

Which means that when we mark a method as virtual, we are informing the compiler that the derived type for this base type shall "override" this implementation with its own implementation.


    public class Cat : Animal
    {
        public override void Sound()
        {
            // extending the base implementation
            // uncommenting this line shall
            // call the base implementation
            // base.Sound();
            Console.WriteLine("Cat makes Sound");
        }
    }

And when you run it, the output


Cat makes Sound  // Comes from the a.Sound() overriding method
Cat makes Sound  // Comes from the c.Sound() instantiated method

When virtual and override is desired? When we have a base type which has some implementation, and we are anticipating some extension for it in a newer version of itself in the near future. Then we shall mark it as virtual, so that the next iteration of it can carry it forward with its own implementation without having to change it.

Scenario 2 - abstract and override:

Now let's assume there is a base type to the Animal type which is an abstract template for the concrete Animal type. Let's call it BaseAnimal which is as below:


namespace WorkConsoleApp
{
    public abstract class BaseAnimal
    {
        public abstract void Sound();
    }
}

Now when we extend this type to our derived Animal type as below:


    public class Animal : BaseAnimal
    {
        // Concrete Animal implementation
    }

We can see one compiler error already,


'Animal' does not implement inherited abstract member 'BaseAnimal.Sound()'

Which indicates that when we have an abstract base type with an abstract method extended by a concrete implementation, the concrete derived type should definitely provide an implementation to the abstract base method. Now how do we implement it?


namespace WorkConsoleApp
{
    public abstract class BaseAnimal
    {
        public abstract void Sound();
    }

    public class Animal : BaseAnimal
    {
        public override void Sound()
        {
            Console.WriteLine("Overriding the Animal Base");
        }
    }
    
    public class Cat : Animal
    {
        public override void Sound()
        {
            // extending the base implementation
            // uncommenting this line shall
            // call the base implementation
            // base.Sound();
            Console.WriteLine("Cat makes Sound");
        }
    }
}

We denote that we "override" the base abstract method with our own implementation in our derived type. This is another usecase for "override" keyword which is used in conjunction with an "abstract" keyword. And when we run it using our Main method as below:


    public class NewProgram 
    {
        public static void Main(string[] args) 
        {
            BaseAnimal a = new Animal();
            a.Sound();

            Animal c = new Cat();
            c.Sound();
        }
    }

Gets us the result:


Overriding the Animal Base // from a.Sound() which is of type AnimalBase
Cat makes Sound // from c.Sound()

Scenario 3 - the "new" implementation:

Now instead of virtual and override, we can simply mark the derived type method as a "new" method which informs the compiler that the derived implementation is completely a "new" definition and is not going to shadow its base.


    public class Animal
    {
        public void Sound()
        {
            Console.WriteLine("Animal makes Sound");
        }
    }

    public class Cat : Animal
    {
        public new void Sound()
        {
            Console.WriteLine("Cat makes Sound");
        }
    }

And when we run this as below:


    public class NewProgram 
    {
        public static void Main(string[] args) 
        {
            Animal a = new Cat();
            a.Sound();

            Cat c = new Cat();
            c.Sound();
        }
    }

Gives you the output:


Animal makes Sound
Cat makes Sound

And we observe that the compiler warning doesn't come anymore, since we have marked the derived type method as a "new" method differentiating it from the base method.

Explain async and await
What is the difference between Finalize() and Dispose() methods?
What is the difference between CopyTo and Clone methods?
How can I call the base implementation of an overridden virtual method?
What is LINQ?
We use cookies to provide you with a great user experience, analyze traffic and serve targeted promotions.   Learn More   Accept