Overriding

Overriding

A derived class can override behaviors in the base class, which allows a derived type to substitute different implementations where appropriate. The Pay method of the Employee class is overridden in CommissionedEmployee to include commissions in each paycheck. In the SalariedEmployee class, the Pay method is overridden to calculate pay by prorating annual income. Methods, properties, and indexers can be overridden. Fields and static members of the base cannot be overridden in the derived class. However, derived types can hide fields and static members of the base class.

When is a child class allowed to override the parent? Most parents hope that their children inherit their sterling behavior. However, the behavior of the parent is merely a suggestion to the child. Children are often inclined to override the behaviors of the parents. The parent is hopeless in preventing this substitution. In many object-oriented languages, that is the model. Child or derived classes can override the behavior of the parent or base class. The derived class might override a behavior inappropriately and destabilize the base class. This is called the fragile base class problem: a problem that is acute with class libraries where a child class is more likely to inherit a type and unknowingly or incorrectly override a base member. The model is different in C#. By default, functions cannot be overridden. Parent classes must tacitly approve the overriding of a method. In addition, the child class must acknowledge its intent to override the method. This prevents the child from unknowingly overriding a member of the base class.

Virtual and Override Keywords

The virtual keyword indicates that a member can be overridden in a child class. It can be applied to methods, properties, indexers, and events. In the derived class, the override keyword indicates the intention to override a virtual member of the base class. The virtual and override keywords complement each other. The virtual keyword propagates to descendants. A virtual method is overridable in a derived class and descendants.

Overriding is not an all-or-nothing condition. Using the base keyword, the public and protected members of the base class are accessible in the derived type. The syntax is base.member. You cannot skip levels with the base keyword. For example, you cannot access a member in a grandfather class. The base.base.member syntax is illegal. In the following code, the SalariedEmployee.Pay method calls the Employee.Pay method to display an employee name on a paycheck:

public class Employee: ICloneable {

    public Employee() {
    }

    public Employee(int id) {
        if((id<1000) || (id>9999)) {
            throw new Exception(
                "Invalid Employee ID");
        }

        propID=id;
    }

    public virtual void Pay() {
        Console.WriteLine("Employee: "+FullName);
    }

    // partial listing
}

public class SalariedEmployee: Employee {

    public override void Pay() {
        base.Pay();
        Console.WriteLine("Pay is: {0,6:c}",
            propSalary/(decimal)propPeriods);
    }

    // partial listing

}

Overload versus Override

Override and overload are different concepts. When a member of a base class is overridden, the signature of the base and the signature of the derived member are the same. Overloading requires different signatures. In a derived class, a function can be overloaded, overridden, or both. When a member is overridden with a different signature, a compiler warning occurs in the derived type. This prevents an accidental overload, where method overriding was intended. This is shown in the following code, where MethodA is overloaded in the YClass class but not overridden. In Main, both the base and the derived implementation are called.

using System;

namespace Donis.CSharpBook{

    public class Starter{

        public static void Main(){
            YClass obj=new YClass();
            obj.MethodA();
            obj.MethodA(10);
        }
    }


    public class ZClass {
         public virtual void MethodA() {
             Console.WriteLine("ZClass.MethodA");
        }
    }

    public class YClass: ZClass
    {
        public override void MethodA(int a) {
            Console.WriteLine("YClass.MethodA");
        }

    }
}

Overriding Events

For completeness, the following is sample code for overriding an event. Events are discussed in Chapter 8, "Delegates and Events."

public class ZClass {

     public virtual void MethodA() {
     }

     public delegate void MyDel();
     public virtual event MyDel MyEvent {
         add{
         }
         remove{
         }
     }
}

public class YClass: ZClass {

     public override event MyDel MyEvent{
         add{
             // different implementation
         }
         remove{
             // different implementation
         }
     }
}