#350 – Method Modifiers Required for Polymorphic Behavior

There are three combinations of method modifiers that make sense, in determining whether methods in a class are virtual or non-virtual.

Typical combinations of modifiers for base class / derived class (assuming that method signature is the same in both the base and derived class):

  • (no modifier) / new – Both methods are non-virtual, derived class method hides the base class method
  • virtual / override – Both methods are virtual, support polymorphic behavior
  • virtual / new – Base class method virtual, derived class method non-virtual, derived class method hides base class method

There are two other combinations that are allowed, but result in a compiler warning indicating that you should use new in the derived class to be explicit:

  • (no modifier) / (no modifier) – effectively (no modifier) / new
  • virtual / (no modifier) – effectively virtual / new
Advertisements

#349 – The Difference Between Virtual and Non-Virtual Methods

In C#, virtual methods support polymorphism, by using a combination of the virtual and override keywords.  With the virtual keyword on the base class method and the override keyword on the method in the derived class, both methods are said to be virtual.

Methods that don’t have either the virtual or override keywords, or that have the new keyword, are said to be non-virtual.

When a virtual method is invoked on an object, the run-time type of the object is used to determine which implementation of the method to use.

When a non-virtual method is invoked on an object, the compile-time type of the object is used to determine which implementation of the method to use.

#345 – Method in Derived Class Hides Base Class Method by Default

If you define a method in a derived class with the same name and signature as a method in the base class, the new method hides the base class method by default.  This is true even if you don’t use the new keyword to explicitly indicate that you intend to hide the method in the base class.

In other words, if we have a Dog.Bark method, the following two code snippets are functionally equivalent.

    public class Terrier : Dog
    {
        public new void Bark()
        {
            Console.WriteLine("Terrier {0} is barking", Name);
        }
    }

 

    public class Terrier : Dog
    {
        // No new keyword, but we're still hiding base class method
        public void Bark()
        {
            Console.WriteLine("Terrier {0} is barking", Name);
        }
    }

Without the new keyword, the compiler warns you that you’re hiding the base class method and recommends using the new keyword.

#344 – Hidden Base Class Member Is Invoked Based on Declared Type of Object

When you use the new modifier to hide a base class method, it will still be called by objects whose type is the base class.  Objects whose type is the derived class will call the new method in the derived class.

            Dog kirby = new Dog("Kirby", 15);

            // Calls Dog.Bark
            kirby.Bark();

            Terrier jack = new Terrier("Jack", 17);

            // Calls Terrier.Bark
            jack.Bark();

The Terrier.Bark method is invoked because the variable jack is declared to be of type Terrier.

We could also use a variable of type Dog (the base class) to refer to an instance of a Terrier (the derived class).  If we then call the Bark method using this base class variable, the Bark method in the base class is called, even though we’re invoking the method on an instance of the derived class.

            Dog kirby = new Dog("Kirby", 15);

            // Calls Dog.Bark
            kirby.Bark();

            Dog jack = new Terrier("Jack", 17);

            // Calls Dog.Bark
            jack.Bark();

#343 – Use the new Keyword to Replace a Method in a Base Class

A derived class inherits data and behavior from its parent class.

There are times when you might want to replace a method in a base class with a new method in the derived class, having the same name.  You can do this using the new keyword.

Assume a Dog class has a Bark method:

    public class Dog
    {
        public void Bark()
        {
            Console.WriteLine("Generic dog {0} says Woof", Name);
        }

You can provide a new version of this method in a class that derives from Dog, using the new keyword.  This new method hides the method in the base class.

    public class Terrier : Dog
    {
        public new void Bark()
        {
            Console.WriteLine("Terrier {0} is barking", Name);
        }

Dog objects will now invoke Dog.Bark and Terrier objects will invoke Terrier.Bark.

            Dog kirby = new Dog("Kirby", 15);
            kirby.Bark();

            Terrier jack = new Terrier("Jack", 17);
            jack.Bark();