[C#] Shadowing

Polymorphism is what makes OOP so unique and powerful.

In C#, polymorphism works with “virtual / abstract” methods and “override” methods. But using these keywords can be tricky in some cases and might result in confusing results.

 

1. Polymorphism

The following example is the most basic usage of Polymorphism.

  • Define the virtual or abstract method in a base class
  • Override the method in a derived class
public abstract class Vehicle
{
  public virtual void Move()
  {
    Console.WriteLine("What am I? How can I move?");
  }
}

public class Car : Vehicle
{
  public override void Move()
  {
    Console.WriteLine("I am moving 60 km/h ...");
  }
}

Vehicle car = new Car();
car.Move(); // I am moving 60 km/h ...

 

2. Shadowing – Case 1

What if we omit the “override” keyword in the derived class “Car”?

public abstract class Vehicle
{
  public virtual void Move()
  {
    Console.WriteLine("What am I? How can I move?");
  }
}

public class Car : Vehicle
{
  public void Move()
  {
    Console.WriteLine("I am moving 60 km/h ...");
  }
}

Vehicle car1 = new Car();
car1.Move(); // What am I? How can I move?
Car car2 = new Car();
car2.Move(); // I am moving 60 km/h ...

Surprisingly, you do not get an error but “Polymorphism” does not work any more.

Actually, you can find a warning in the “Error List”.

‘Car.Move()’ hides inherited member ‘Vehicle.Move()’. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword.

 

3. Shadowing – Case 2

Let’s define the “SportsCar” class that derives from “Car”. If you specify the “override” keyword in both “Car” and “SportsCar”, there is no doubt that “Polymorphism” will work.

What if we omit “override” in the derived class?

public class Car : Vehicle
{
  public override void Move()
  {
    Console.WriteLine("I am moving 60 km/h ...");
  }
}

public class SportsCar : Car
{
  public void Move()
  {
    Console.WriteLine("I am moving 150 km/h Ha Ha...");
  }
}

Vehicle car1 = new Car();
car1.Move(); // I am moving 60 km/h ...
Vehicle car2 = new SportsCar();
car2.Move(); // I am moving 60 km/h ...

You will get a warning again.

‘SportsCar.Move()’ hides inherited member ‘Car.Move()’. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword.

The warning message is quite helpful. And you can find that “Polymorphism” does not work.

 

4. “new” vs “override”

When you do redefine the virtual method in a derived class, you have two choices:

  • override“: works in a polymorphic way
  • new“: the new implementation will ignore the base class’s version

If you do not specify “override” or “new“, it works as the “new” keyword is specified.

public class Car : Vehicle
{
  public override void Move()
  {
    Console.WriteLine("I am moving 60 km/h ...");
  }
}

public class SportsCar : Car
{
  public new void Move()
  {
    Console.WriteLine("I am moving 150 km/h Ha Ha...");
  }
}

Vehicle car1 = new Car();
car1.Move(); // I am moving 60 km/h ...
Vehicle car2 = new SportsCar();
car2.Move(); // I am moving 60 km/h ...
SportsCar car3 = new SportsCar();
car3.Move(); // I am moving 150 km/h Ha Ha...

 

5. Shadowing

In the Polymorphic scenario, which version of method is invoked is decided at runtime.

But when you use a “new” keyword, the compiler decides which version of method is called by the type of the variable, not by the runtime object type.

This behavior is called “Shadowing“.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s