Overriding Inherited Behavior

A derived class can override behavior inherited from the base class, which allows a derived type to apply more specific behavior. The Pay method of the Employee class is overridden in CommissionedEmployee to consider commissions when calculating a paycheck. In the SalariedEmployee class, the Pay method is overridden to calculate pay by prorating annual income. Methods, properties, indexers, and events can be overridden. Fields and static members cannot be overridden. However, they can be hidden in the derived class.

Can a child override a member of the parent at any time? With human beings, most parents hope that their children inherit and observe their recommended behavior. However, the behavior of the parent is merely a suggestion to the children. Children often are inclined to override the behavior of the parent, and the parent is helpless to prevent this. In many object-oriented languages, that is essentially the model. Child or derived classes can, without restriction, override the behavior of the parent or the base class. This openness means a derived class can inappropriately override a behavior and break the code inherited from 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 unknowingly or incorrectly override a base member. The model is different in C#. By default, methods cannot be overridden. Parent classes identify members that are available for overriding. In addition, the child class must acknowledge its intent to override the method. This prevents the child from inadvertently overriding a member of the base class.

Virtual and Override Keywords

The virtual keyword indicates that a member is a candidate for being overridden in a derived class. Virtual can be applied to methods, properties, indexers, and events. In the derived class, the override keyword indicates an intention to override a virtual member of the base class. The virtual and override keywords complement each other. The virtual keyword propagates to all descendants. This means that the virtual method is overridable in not just the most immediate derived class, but in all 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 as follows:

base.member

You cannot skip levels of class hierarchy with the base keyword. For example, you cannot access a member in a grandfather class. Syntax such as base.base.member is illegal. With the base keyword, you can have both the derived and base behavior. In the overridden method, simply call the base behavior using the base keyword. This is demonstrated in the following code. With the base keyword, 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 identical. 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 error occurs in the derived type. This prevents an accidental overload, when 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

Events are implemented using an add and remove method pair. The following is sample code for overriding an event. Events are discussed in detail in Chapter 10.

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
         }
     }
}

Extension Method

Microsoft Visual C# 2008 provides integers as a primitive type. What if the integer type (or any type, for that matter) is inadequate for your purposes? You might want to extend the interface of that type to include additional behavior. That is the purpose of extension methods. An extension method extends the interface of an object, which allows you to extend the otherwise closed interface of a type.

Extension methods are defined as static methods in a static class. The first parameter of the extension method must be the this keyword followed by the type of the target object. The type defines where the extension method can be applied. You can call the extension method on an object of that type, just as you would call a normal method.

Here is sample code of an extension method. In the sample code, extension methods are created for an integer type. The extension methods return true or false depending on whether the integer is an odd or even number:

static class IntegerExtensions {
    public static bool IsOdd(this int number) {
        return (number % 2) == 0 ? false : true;
    }

    public static bool IsEven(this int number) {
        return (number % 2) == 0 ? true : false;
    }
}
class Startup {
    public static void Main() {
        bool result = 6.IsOdd();
        if (result) {
            Console.WriteLine("odd");
        }
        else{
            Console.WriteLine("even");
        }
    }
}

Extension methods also can be applied to interfaces. Then you can use the extension method on any object that implements that interface. In the following code, two extension methods are defined for the IDisposable interface. The methods are fairly straightforward as to their purpose. In Main, the DisposeAndTrace extension method is called on the instance of a ZClass, which implements the IDisposable interface. The IDisposable extensions can be called on any object that implements the IDisposable interface:

static class DisposableExtensions {
    public static void DisposeAndCollect(this IDisposable obj) {
        obj.Dispose();
        GC.Collect();
    }

    public static void DisposeAndTrace(this IDisposable obj) {
        obj.Dispose();
        System.Diagnostics.Debug.WriteLine("Disposed " + obj.ToString());
    }
}

class ZClass : IDisposable {
    public void Dispose() {
        // cleanup resources
    }
}
class Startup {
    public static void Main() {
        ZClass obj = new ZClass();
        obj.DisposeAndTrace();
    }
}

The following additional rules pertain to extension methods:

  1. If an instance method and extension method have identical signatures, the instance method is called.

  2. If two extension methods have identical signatures, either extension method must be called as a normal static method.

  3. The static class of the extension method must be within scope. If it is not, the extension method cannot be called.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.218.239.182