Wednesday, September 15, 2010

Polymorphism in C#

  • When a message can be processed in different ways is called polymorphism."Poly" means many
  • When you derive a class from a base class, the derived class will inherit all members of the base class except constructors, though whether the derived class would be able to access those members would depend upon the accessibility of those members in the base class
  • C# gives us polymorphism through inheritance. Inheritance-based polymorphism allows us to define methods in a base class and override them with derived class implementations. Thus if you have a base class object that might be holding one of several derived class objects, polymorphism when properly used allows you to call a method that will work differently according to the type of derived class the object belongs to
  • It allows you to invoke methods of derived class through base class reference during runtime
  • It has the ability for classes to provide different implementations of methods that are called through the same name
Polymorphism is of two types:
  • Compile time polymorphism/Overloading
  • Runtime polymorphism/Overriding
Compile Time Polymorphism
  • Compile time polymorphism is method and operators overloading. It is also called early binding
  • In method overloading method performs the different task at the different input parameters
  • Use method overloading in situation where you want a class to be able to do something, but here is more than one possibility for what information is supplied to the method that carries out the task
  • You should consider overloading a method when you for some reason need a couple of methods that take different parameters, but conceptually do the same thing
Example
 using System;
namespace method_overloading

{
class Program
{
public class Print
{
public void display(string name)

{
Console.WriteLine("Your name is : " + name);
}

public void display(int age, float marks)

{
Console.WriteLine("Your age is : " + age);

Console.WriteLine("Your marks are :" + marks);
}
}

static void Main(string[] args)

{
Print obj = new Print();

obj.display("George");

obj.display(34, 76.50f);

Console.ReadLine();
}
}
}
Main points to be remembered while overloading are
  • If you use overload for method, there are couple of restrictions that the compiler imposes
  • The rule is that overloads must be different in their signature, which means the name and the number and type of parameters
  • There is no limit to how many overload of a method you can have. You simply declare them in a class, just as if they were different methods that happened to have the same name
Here is an example to overload multiple methods
using System;
namespace method_overloading_polymorphism
{
class Program
{
public class Shape

{
public void Area(float r)
{
  float a = (float)3.14 * r;

  // here we have used funtion overload with 1 parameter.

  Console.WriteLine("Area of a circle: {0}",a);
}

public void Area(float l, float b)

{
  float x = (float)l* b;

  // here we have used funtion overload with 2 parameters.

  Console.WriteLine("Area of a rectangle: {0}",x);

}
public void Area(float a, float b, float c)

{
  float s = (float)(a*b*c)/2;

  // here we have used funtion overload with 3 parameters.

  Console.WriteLine("Area of a circle: {0}", s);
}
}
static void Main(string[] args)
{
Shape ob = new Shape();

ob.Area(2.0f);

ob.Area(20.0f,30.0f);

ob.Area(2.0f,3.0f,4.0f);

Console.ReadLine();
}
}
}
Runtime Time Polymorphism
  • Runtime time polymorphism is done using inheritance and virtual functions. Method overriding is called runtime polymorphism
  • It is also called late binding.
Let's assume the following simple class hierarchy with classes A, B and C for the discussions in this text. A is the super- or base class, B is derived from A and C is derived from class B. In some of the easier examples, we will only refer to a part of this class hierarchy.

Inherited Methods

A method Foo() which is declared in the base class A and not redeclared in classes B or C is inherited in the two subclasses

using System;
namespace Polymorphism
{
class A
{
 public void Foo() { Console.WriteLine("A::Foo()"); }
}

class B : A {}

class Test
{
 static void Main(string[] args)
 {
     A a = new A();
     a.Foo();  // output --> "A::Foo()"

     B b = new B();
     b.Foo();  // output --> "A::Foo()"
 }
}
}
The method Foo() can be overridden in classes B and C:
using System;
namespace Polymorphism
{
class A
{
     public void Foo() { Console.WriteLine("A::Foo()"); }
}
class B : A
{
     public void Foo() { Console.WriteLine("B::Foo()"); }
}
class Test
{
   static void Main(string[] args)
   {
       A a;
       B b;
       a = new A();
       b = new B();
       a.Foo();  // output --> "A::Foo()"
       b.Foo();  // output --> "B::Foo()"
       a = new B();
       a.Foo();  // output --> "A::Foo()"
   }
}
}
There are two problems with this code.
  • The output is not really what we, say from Java, expected. The method Foo() is a non-virtual method. C# requires the use of the keyword virtual in order for a method to actually be virtual. An example using virtual methods and polymorphism will be given in the next section
  • Although the code compiles and runs, the compiler produces a warning: ...\polymorphism.cs(11,15): warning CS0108: The keyword new is required on 'Polymorphism.B.Foo()' because it hides inherited member 'Polymorphism.A.Foo()'

This issue will be discussed in section Hiding and Overriding Methods.

Virtual and Overridden Methods

Only if a method is declared virtual, derived classes can override this method if they are explicitly declared to override the virtual base class method with the override keyword.

using System;
namespace Polymorphism
{
class A
{
    public virtual void Foo() { Console.WriteLine("A::Foo()"); }
}

class B : A
{
    public override void Foo() { Console.WriteLine("B::Foo()"); }
}

class Test
{
    static void Main(string[] args)
    {
        A a;
        B b;

        a = new A();
        b = new B();
        a.Foo();  // output --> "A::Foo()"
        b.Foo();  // output --> "B::Foo()"

        a = new B();
        a.Foo();  // output --> "B::Foo()"
    }
}
}

Method Hiding

Why did the compiler in the second listing generate a warning? Because C# not only supports method overriding, but also method hiding. Simply put, if a method is not overriding the derived method, it is hiding it. A hiding method has to be declared using the new keyword. The correct class definition in the second listing is thus:

using System;
namespace Polymorphism
{
  class A
  {
      public void Foo() { Console.WriteLine("A::Foo()"); }
  }

  class B : A
  {
      public new void Foo() { Console.WriteLine("B::Foo()"); }
  }

  class Test
  {
      static void Main(string[] args)
      {
          A a;
          B b;

          a = new A();
          b = new B();
          a.Foo();  // output --> "A::Foo()"
          b.Foo();  // output --> "B::Foo()"

          a = new B();
          a.Foo();  // output --> "A::Foo()"
      }
  }
}

Combining Method Overriding and Hiding

Methods of a derived class can both be virtual and at the same time hide the derived method. In order to declare such a method, both keywords virtual and new have to be used in the method declaration:

class A
       {
           public void Foo() {}
       }

       class B : A
       {
           public virtual new void Foo() {}
       }


A class C can now declare a method Foo() that either overrides or hides Foo() from class B:

       class C : B
       {
           public override void Foo() {}
           // or
           public new void Foo() {}
       }

No comments:

Post a Comment