Thursday, April 12, 2007

A brief look at Polymorphism and how it is used...

What is Polymorphism?


Polymorphism is the ability to use a class as more than one type. The class can use a derived type or its own type. The most common use of polymorphism is redefining a method; this can be accomplished by either replacing the members of the base class with the derived class’ members or overriding the members of the base class. 


To make this a little more clear I will break down this definition into more manageable terminology. You basically use polymorphism every time you create an object that uses the members of a class (such as in previous blogs I had created objects that implemented members of the Base_Patient and Derived_Patient classes). Microsoft has stated that all objects in C# are an instance of polymorphism. The basic idea is that you are allowing the derived class or object to implement methods, properties and events in manners different than that of which the base class already implements them.


How do I use polymorphism?


An example of using polymorphism would be if in a doctor’s office they had wanted to track the distance of walking a patient could do within a given time frame and then compare this to an average distance of other patients within the same age span. 


To begin we would create a class that sets the properties that all patients have in common. We know that all patients have a first name, last name and age. In this sample I had created a class called “Base_Patient” and placed the following code in it:






using System;
using System.Collections.Generic;
using System.Text; 


namespace polymorphism_1
{
    class Base_Patient
    {
        //This creates our strong type variables that we will
        //want to allow to be accessed from outside of our class.
        public string strFirstName,
            strLastName; 


        public int intAge; 


        //default constructor for base class
        public Base_Patient() { } 


        //We create the constructor requiring the values of 
        //the patient at the time the class is constructed. 
        //Notice later a property of "Age" is created; however, we
        //do not use it in this constructor..it wil be used later
        //in the derived class (when polymorphing this constructor).
        public Base_Patient(string strFN, string strLN)
        {
            strFirstName = strFN;
            strLastName = strLN;
        } 


        //destructor of object class
        ~Base_Patient() { } 


        //We set our property accessors as private so we may
        //ensure that an outside class has to assign these values
        //through our predetermined methods. This is considered a
        //best practice. 


        //property firstName of patient
        private string FirstName
        {
            get
            {
                return strFirstName;
            }
            set
            {
                strFirstName = value;
            }
        } 


        //property lastName of patient
        private string LastName
        {
            get
            {
                return strLastName;
            }
            set
            {
                strLastName = value;
            }
        } 


        //property Age of patient
        private int Age
        {
            get
            {
                return Age;
            }
            set
            {
                intAge = value;
            }
        } 


        //We declare our methods as public so our derived objects
        //can polymorph them later.
        public void DisplayName()
        {
            Console.WriteLine("This patients name is: " + strFirstName + " " + strLastName);
        } 


        public void DisplayAge()
        {
            Console.WriteLine("This patient is: " + intAge + " years old.");
        } 


        //You will notice the method to display the 
        //RateofWalk does not contain implementation code,
        //this is because we will force any derived class to
        //create the method (polymorph this method).
        //We use the modifier "virtual" because it allows a derived class to
        //override this method. We also set these methods to return an expected
        //integer (of double type) result since we want to perform a calculation.
        //We must use the "double" as the type because during our calculation
        //the result will briefly be a decimal value; the data type "int"
        //cannot handle this type (the result would be rounded to nearest
        //real value..i.e. 0.3 would be 0).
        public virtual void RateOfWalk(double dblPtntRate, double dblMinutesWalked){} 


    }//ends the class
}//ends the namespace

Figure 1 (Base class called “Base_Patient.cs”)

Now that we have our base class we can create our derived class. In this sample I created a class called “Derived_Patient” and placed the following code in it:






using System;
using System.Collections.Generic;
using System.Text; 


namespace polymorphism_1
{
    //This inherits from our base class.
    class Derived_Patient : Base_Patient
    {
        //We create a public variable that will handle the
        //value of our returned rate from our calculation method
        //we will create later when polymorphing the "RateOfWalk" method.
        public double dblPtntReturnedRate; 


        //We create a constructor that polymorphs the base
        //class' constructor method. You can tell because our
        //base class uses only 2 arguments and we use 3 here!
        public Derived_Patient(string strDP_FN, string strDP_LN, int intDP_Age)
        {
            strFirstName = strDP_FN;
            strLastName = strDP_LN;
            intAge = intDP_Age;
        } 


        //Here we override our base class' "RateOfWalk" method, thus
        //we are polymorphing it.
        public override void RateOfWalk(double dblPatientRate, double dblPatientMinutesWalked)
        {
            //Remember that our base class has no defined method
            //procedures? Here we place our procedures as we want. 


            //Here we are calculating the rate of walk for the patient
            //over a specified period of time. Our calculation assumes
            //the "intPtntRate" is the miles walked per hour.
            //We divide the MPH by 60 (minutes in an hour) and multiple by
            //the amount of minutes walked. 
            //I.E. 6 MPH for 30 minutes = .10 miles per minute
            if (intAge >= 55)
            {
                dblPtntReturnedRate = ((dblPatientRate / 60) * dblPatientMinutesWalked);
            }
            else
            {
                //I chose to add the "* 2" at the end of this arithmetic statement
                //based on average someone of much younger age than 55 is assumed
                //to walk twice as fast. The alternate route would be to decrease
                //the divisor of 60 to be 30.
                dblPtntReturnedRate = (((dblPatientRate / 60) * dblPatientMinutesWalked) * 2);
            }
            //This line will output our results into a console window.
            Console.WriteLine("This patient has walked: " + dblPtntReturnedRate + " miles during " + dblPatientMinutesWalked + " minutes!");
        } 


    }//ends the class
}//ends the namespace

Figure 2 (Derived class called “Derived_Patient.cs”)

Now we create our “Program.cs” file and place the following code in it:






using System;
using System.Collections.Generic;
using System.Text; 


namespace polymorphism_1
{
    class Program
    {
        static void Main(string[] args)
        {
            //We create our object as a "new" object and set the name and age
            //of the patient.
            Derived_Patient clsDP = new Derived_Patient("John", "Smith", 62); 


            //The following lines of code will call the polymorphed and unchanged
            //methods of the derived class. You will see that we have the choice
            //of what methods are overriden; as long as the base class does not
            //force overriding or restrict overriding.
            Console.WriteLine("The following 2 lines will display information that isn't polymorphed:");
            clsDP.DisplayName();
            clsDP.DisplayAge();
            Console.WriteLine();
            Console.WriteLine("This line will display the polymorphed method in our derived class");
            //RateOfWalk requires 2 arguments: Miles walked per hour, and
            //amount of time walked by the patient.
            clsDP.RateOfWalk(6, 30);
            Console.ReadLine();
        }


    }//ends the class
}//ends the namespace

Figure 3 (Program file called “Program.cs”)

You can see from above that polymorphing had happened intentionally, by creating a method for the “RateOfWalk” that was originally declared in the base class and later used in the derived class. Another instance of polymorphism, although much more subtle, is when we created our constructor of the derived class. The base class contained a property for the patient’s age; however, the constructor of the base class did NOT set this property. When we created the constructor of the derived class we had added the requirement of the patient’s age, thus creating a polymorphed constructor (albeit unconventional). 


The calculations used in the “RateOfWalk” method in the derived class may not be practical (I chose this method so I can also demonstrate the use of an “if” statement), and especially not clear cut; although it should show clearly that you can create different implementation code for methods declared in other base classes. Don’t get hung up on what the code is calculating or why it is; just remember that we did not have any implementation code of the method in the base class and we were able to create the implementation code in the derived class! 


Keep in mind this blog is only introducing you to the concept of “polymorphism”, there are many more features and rules than what I can cover. There are many resources available; books have chapters discussing this, websites have sections and forums discussing this and you will come across it in many examples (rather you realize it or not). The best starting point I can give you, without requiring the purchasing of materials, is to refer you to Microsoft’s website discussing “polymorphism”. It is a decent starting point; however, it does get very technical. Google is another good way to find out more information; do be aware that “polymorphism” is slightly different in programming languages, so you should ensure that you are reading material related to C# programming. 


Happy coding!

No comments: