December 26, 2013

Advanced CSharp Part 1 : Overriding Methods, Abstract and Sealed Classes

We shall take a step further on our CSharp journey. We shall take a look at some of the complex object oriented programming practices. We have already learnt how to declare classes and methods, we also know about method overloading. In this post, we shall take a look at somewhat a close cousin called method overriding. In addition we shall take a look at abstract and sealed classes. These concepts are seldom used in small projects like console applications, but influences heavily in large projects or developing third party libraries.

Overriding Methods: Overriding is the ability to control method behavior in object oriented programming. If you are familiar with OOP based languages like Java, you already know how they work. Lets look into a practical example.

Inheritance and Methods
Any region bounded by four sides is a quadrilateral. Three very common variants of a quadrilateral are rectangle, square and a parallelogram. We can safely assume that these three variants inherit some basic properties from the very basic and common: the Quadrilateral. So Quadrilateral is a base class; Rectangle, Square and Parallelogram each inherit Quadrilateral class and are each known as a subclass. Lets assume that Quadrilateral has a Draw() method, which draws a quadrilateral. Evidently you would like to create the same method for each of the subclasses, because you want to draw them as well! You can obviously keep distinct names, but in case of programming, it is advisable to keep relevant names. In this case, the only relevant name is Draw(). But since the base class also owns the very same method, as a subclass you would Override the base class method. What really amazes is the fact that when you want to draw, lets say a rectangle, it calls the Draw() method inside the rectangle class, not anything else! How good is that! Your compiler automatically knows which method you are referring to, so it does not get confused when you call an overriding method.

Before jumping over the code section, we need to understand three related keywords:
  • virtual : This keyword tells the compiler that this method can be overridden by subclasses. The subclasses aren't bound to override this method, but they might want to!
  • override : This tells the compiler that it is overriding its namesake method that can be found in the base class.
  • base : You use this keyword from the overridden method at the subclass when you feel that you want to actually call the method at the base class.
Lets take a look at these keywords in action.

using System;

namespace Spells
{
    class Quadrilateral
    { 
        // some variables, properties and other methods
        public virtual void Draw()
        {
            Console.WriteLine("Drawing a quadrilateral.");
        }
    }
    class Square : Quadrilateral
    {
        // some variables, properties and other methods
        public override void Draw()
        {
            Console.WriteLine("Overridden: Drawing a square.");
        }
    }
    class Rectangle : Quadrilateral
    {
        // some variables, properties and other methods
        public override void Draw()
        {
            Console.WriteLine("Overridden: Drawing a rectangle and also feels like calling base class method.");
            base.Draw();   // this line calls the base class Draw method
        }
    }
    class Program
    {
        public static void Main(string[] args)
        {
            Square sq = new Square();
            sq.Draw();
            Rectangle rect = new Rectangle();
            rect.Draw();
            Quadrilateral quad = new Square();
            quad.Draw();
            Console.Read();
        }
    }
}
Observe line 34 to 37. A square and rectangle type object has been created and when you call the Draw method, it calls the respective overridden method. Line 27 calls the base class implementation of the Draw method. You may choose to call the base class method at your will. At line 38, I have created an object of name Quadrilateral but instantiated it by a subclass called Square. It might seem a little awkward. So what do you think, which Draw method will be called from line 39?
Console output
 As you can see the console output shows that the overridden method at Square has been called. When something like line 38 happens, the compiler calls the lowest descendent of the overridden method, not the ancestor.

Abstract Class: An abstract class like a blueprint model. They cannot be instantiated by themselves, but when you create subclasses from them, you have to instantiate that instead. So what does "blueprint model" interpretation mean here? In abstract classes, there are abstract members that must be overridden by the subclasses and provide functionalities to it. For example, every modern city has building codes, for example buildings cannot be taller than certain heights, they should have sewerage exit and supply of utilities like gas, electricity and water etc. An abstract class is like the building codes, the rules are written there. When someone builds a building (subclass), these rules must be implemented. An abstract class is created by putting the keyword abstract in the class definition. Lets see an easy implementation.

using System;

namespace Spells
{
    abstract class BuildingCodes
    {
        /* no implementation, just a blueprint */
        public abstract void ParkingSpace();
        public abstract bool IsCommercial();
        public abstract bool IsResidential();
    }
    class MyHome : BuildingCodes
    {
        /* must implement all the methods,
         * else a compile time error is generated */
        public override void ParkingSpace()
        {
            // implement logic
        }
        public override bool IsCommercial()
        {
            return false;
        }
        public override bool IsResidential()
        {
            return true;
        }
    }
    class ShoppingMall : BuildingCodes
    {
        /* must implement all the methods,
         * else a compile time error is generated */
        public override void ParkingSpace()
        {
            // implement logic
        }
        public override bool IsCommercial()
        {
            return true;
        }
        public override bool IsResidential()
        {
            return false;
        }
    }
    class Program
    {
        public static void Main(string[] args)
        {
            // BuildingCodes bcodes = new BuildingCodes();    //this is error
            MyHome home = new MyHome();
            ShoppingMall shop = new ShoppingMall();
            Console.WriteLine("Commercial home? {0}\nCommercial Shop? {1}", home.IsCommercial(), shop.IsCommercial());
            Console.Read();
        }
    }
}
Copy and paste this code in your CSharp editor. Go ahead and make line 50 visible. What do you see? An abstract class cannot be instantiated. Then go to any of the subclass, comment-out any of the three overridden methods. Hit F5. A compile time error is generated and asks you to implement an unimplemented method. So why and when should you use an abstract class?
  • When you think that certain things must be implemented in the subclasses.
  • When you want to force programmers to implement something in the subclass.
  • When you have an abstract idea of doing something, but you really don't know how to do them and keep them safe for later implementation.
Sealed Classes and Methods: When you seal-off something, you make sure that it remains intact, no one else touches that thing. Sealed classes and methods basically come up with the same idea. It is quite opposite of the abstract classes. A Sealed class prevents you from subclassing it. You cannot create a subclass of a sealed class. Similarly you cannot override a sealed method. You can seal methods separately in a non-sealed class. But I think sealing method is a redundant idea because a subclass cannot override a base class method unless you make it virtual. This is how you create a sealed class.

sealed class MyClass
{ 
        /* implement code */
}
Go ahead and make the classes in the code snippets above sealed and then try to subclass them. 
You seal a class when you do not want to mess around by creating subclasses of this class. For example when you develop a 3rd party library and you would like to share your project with other developers, often you would love to see others being unable to mess around with certain security-sensitive data and methods. If you want to learn more about sealed classes, the MSDN explains their reason to have such a feature. Click here.

I hope that the advanced CSharp things seemed to you easier and merrier. In the future posts, we shall see something more, something more advanced!

No comments:

Post a Comment