A Twisted Look at Object Oriented Programming in C#

Shadow Fields, Override Virtual Methods

Well, I am going to finish this "nuts and bolts" chapter before I flame out! I promised that I would discuss overriding, so I am going to make good on this promise. In general when you extend a class, you shadow fields with the same name in the base class and override virtual methods with the same name and parameter list in the base class. Overriding makes the base class method invisible. Shadowing a field, only hides the field from view. You can still explicitly touch the hidden shadowed field if you wish. You cannot touch an invisible overridden method. To demonstrate the difference between shadowing and overriding I resort, as usual, to twisted code!

First, you can create a sample base class with a public read only field "toastTime" and a virtual method "MakeToast()":

class Base
{
    public readonly int toastTime= 60;
    public virtual void MakeToast()
    {
        System.Console.WriteLine("MakeToastInSeconds: " + toastTime.ToString());
    }
}

Declaring the only method virtual explicitly allows a designer to override the MakeToast() method in a subclass. (Contrast this to the approach in Java in which all methods are virtual by default.) This is important, since you are explicitly allowing a subclass to completely rewrite the implementation of the MakeToast() method and in doing so make it totally invisible!

Shadow Fields, Override Methods in the Base Class

Now you can extend or subclass the class Base:

/// <summary>
/// Summary description for SubClass
/// </summary>
class SubClass : Base
{
    public readonly new int toastTime= 1;
    public override void MakeToast()
    {
        System.Console.WriteLine("MakeToastInMinutes:" + toastTime.ToString());
    }
}

Note: You must explicitly tell the compiler that you are overriding the virtual base class method MakeToast() with the key word override and that you are hiding the base field with the key word new. (You cannot override a field in a base class.)

Overriding the method MakeToast makes the base class method with the same name and signature invisible to the caller of the class. This is in contrast to the base class field toastTime. The base class field toastTime is shadowed, but still potentially visible to the caller. You have shadowed a base class field and overridden a base class method.

You can demonstrate the behavior of shadowed fields with the following test code:

SubClass sc= new SubClass();
System.Console.WriteLine(sc.toastTime.ToString()); // --> 1
Base super= (Base)sc;
System.Console.WriteLine(super.toastTime.ToString()); // --> 60

In the above code snippet, the type of the reference variable determines which value of toastTime can be touched with the reference variable. Touching the field with a reference of type SubClass tells the compiler that you want to touch the the toastTime field of class SubClass. Casting the reference variable to the base type, tells the compiler that you want to touch the toastTime field of the type Base. Both fields are potentially visible to the caller. The base class field is shadowed, but still touchable.

You can demonstrate the behavior of an overridden method with the following test code. This code demonstrates that the overridden base class method MakeToast is invisible. You cannot touch the overridden method even if you cast the reference to the base type.

SubClass sc= new SubClass();
sc.MakeToast(); // --> MakeToastInMinutes: 1
Base super= (Base)sc;
super.MakeToast(); // --> MakeToastInMinutes: 1

Despite the cast, only the derived (specialized) class method is visible. If you think about it, this behavior is absolutely essential to polymorphism. Overriding insures that the "proper" implementation of a polymorphic method is called at runtime. You can demonstrate the proper polymorphic behavior with a little sample code. Here is yet another version of the Drawable class, now with a default implementation of DrawYourself.

class Drawable
{
    public virtual void DrawYourself()
    {
        System.Console.WriteLine("Drawable");
    }
}
class Square : Drawable
{
    public override void DrawYourself()
    {
        System.Console.WriteLine("Square");
    }
}
class Circle : Drawable
{
    public override void DrawYourself()
    {
        System.Console.WriteLine("Circle");
    }
}

Here is the sample code that demonstrates that the "proper" implementation is called at runtime.

Drawable draw= new Drawable();
draw.DrawYourself(); //--> Drawable
draw= new Square();
draw.DrawYourself(); //--> Square
draw= new Circle();
draw.DrawYourself(); //--> Circle

Overriding insures that the proper super class implementation is always called at runtime. The magic of polymorphism is secure.

You Can Hide a Method

For completeness sake, I will mention that you can hide a virtual method using the key word new instead of the key word override. Go ahead. Edit the previous code sample and replace the key word override with the key word new.

This is the new behavior that breaks polymorphism:

Drawable draw= new Drawable();
draw.DrawYourself(); //--> Drawable
draw= new Square();
draw.DrawYourself(); //--> Drawable
draw= new Circle();
draw.DrawYourself(); //--> Drawable

Perhaps not what you wanted!


You might also like...

Comments

Contribute

Why not write for us? Or you could submit an event or a user group in your area. Alternatively just tell us what you think!

Our tools

We've got automatic conversion tools to convert C# to VB.NET, VB.NET to C#. Also you can compress javascript and compress css and generate sql connection strings.

“If Java had true garbage collection, most programs would delete themselves upon execution.” - Robert Sewell