arrow left
Back to Developer Education

Understanding Polymorphism using Abstract Classes in C#

Understanding Polymorphism using Abstract Classes in C#

According to Microsoft Polymorphism is one of the main concepts in object-oriented programming, after encapsulation and inheritance. Polymorphism is a Greek word that means "many-shaped". In any program, objects of a derived class can be used as objects of a base class using functions parameters and collections or arrays. <!--more-->

Polymorphism is a very helpful concept when it comes to a single abstract idea used in different ways and shapes. With polymorphism, you can define a single abstract class and reshape it in different ways to suit your methods & ideas.

Table of contents

  • Understand the concept of polymorphism.
  • Understand abstract classes.
  • Multiple examples of polymorphism.

Prerequisites

To follow along with this article, you'll need the following:

  • A basic understanding of the C# programming language.
  • A basic understanding of Inheritance in C# programming language.

If you're new to Inheritance, you should check this tutorial that would help you understand the concept.

Abstract classes

Abstract classes are very simple and generic, and they are always used as base classes. Abstract classes have no meaning on their own, derived classes must be defined to complete the meaning, and they could contain abstract methods or abstract properties.

Basically, abstract classes will never be used if not inherited, because they have no meaning on their own, and their variables & methods are useless if not overridden by other inherited classes.

The following example will explain how we can define an abstract class to make a payroll system using Polymorphism.

Worker class

Worker is an abstract generic class that will be used later on for the other inherited classes. First, we will define the Constructor, set() and get() methods of the class.

public abstract class Worker
{
  private string FSname;
  private string LSname;

  // constructor of class
  public Worker(string FSnameval, string LSnameval)
  {
      FSname = FSnameval;
      LSname = LSnameval;
  }
  // Set & Get for FSname
  public string Fsname
  {
      get
      {
        return Fsname;
      }
      set
      {
        Fsname = value;
      }
  }
  // Set & Get for LSname
  public string Lsname
  {
     get
     {
      return Lsname;
     }
     set
     {
      Lsname = value;
     }
  }
  // return a string of the Worker information
  public override string ToString()
  {
     return FSname + " " + LSname;
  }
  
  // calculating the income of a worker. This is an abstract property that must be defined by the inherited classes.
  public abstract decimal Income();  
}

Chief class

This class will use the previous class and its properties & methods for the definition of a chief payroll.

public class Chief : Worker
{
  private decimal salary; 

  // constructor of Chief class
  public Chief(string FSname, string LSname, decimal salary) : base(FSname, LSname)
  {
      Weeklyincome = salary;
  }
  // Get & Set for the Weeklyincome
  public decimal Weeklyincome
  {
     get
     {
      return salary;
     }
     set
     {
      // only positive salary value
      if (value > 0 )
         salary = value;
     }
  }

The following code will override the ToString() & Income() methods:

  // override worker method to calculate the Income
  public override decimal Income()
  {
    return Weeklyincome;
  }

  // return a string of the Chief information
  public override string ToString()
  {
  return "Chief: " + base.ToString();
  }
}

Commissionemp class

This class will use the main abstract class and its properties & methods for the definition of a Commission payroll. The following code will define the Constructor of the class, set & get for the Salary, commission, and amount:

public class Commissionemp : Worker
{
   private decimal salary;
   private decimal commission;
   private int amount;

    // constructor of Commissionemp class
    public Commissionemp(string FSname, string LSname, decimal salary, decimal commission, int amount) : base(FSname,LSname)
  {
      Weeklyincome = salary;
      Commission = commission;
      Amount = amount;
  }

  // set & get for Weeklyincome
  public decimal Weeklyincome
  {
    get
    {
      return salary;
    }
    set
    {
      // positive value
      if (value > 0 )
         salary = value;
    }
   }
  // set & get for Commission
  public decimal Commission
  {
    get
    {
      return commission;
    }
    set
    {
      // positive value
      if (value > 0 )
       commission = value;
       }
    }
  // set & get for amount
  public int Amount
  {
    get
    {
      return amount;
    }
    set
    {
      // positive value
      if (value > 0 )
      amount = value;
    }
  }

The following code will override the ToString() and Income() methods from the main class to store the output:

    // Commissionemp's income.
    public override decimal Income()
    {
        return Weeklyincome + Commission * Amount;
    }
    // return a string of Commissionemp information
    public override string ToString()
    {
      return "Commissionemp: " + base.ToString();
    } 
 } 

Piece_emp class

This class will use the main abstract class and its properties & methods for the definition of a Piece employee payroll. The following code will define the Constructor of the class, set & get for the Paymentforpiece and amount:

public class Piece_emp : Worker 
{
   private decimal Paymentforpiece; 
   private int amount;         

    // constructor of Piece_emp class
    public Piece_emp(string FSname, string LSname, decimal PaymentforP, int amount) : base(FSname,LSname)
    {
       Paymentforpiece = PaymentforP;
       Amount = amount;
    }

    // Set & Get for Paymentforpiece
    public decimal PaymentforP
    {
      get
      {
        return Paymentforpiece;
      }  
      set
      {
        if (value > 0 )
        Paymentforpiece = value;
      }
    }
    // Set & Get for Amount
    public int Amount
    {
      get
      {
        return amount;
      }  
      set
      {
        if (value > 0 )
        amount = value;
      }
    }

The following code will override the ToString() and Income() methods to store the output:

  //Income of Piece_employee
  public override decimal Income()
  {
    return Amount * Paymentforpiece;
  }

  // return string of Piece_emp information
  public override string ToString()
  {
    return "Piece_emp: " + base.ToString();
  }
}

Polymorphism testing

In main, we will create objects of each worker class we have and output the information of each object to test out each one of them.

public class Program
{
  public static void Main(string[] args)
  {
      Chief chief = new Chief("Khaled", "Sans", 800);

      Commissionemp Commemp =
      new Commissionemp("Susan", "Jons", 300, 2, 120);

      Piece_emp piece_emp = new Piece_emp("Samir", "Muan",
         Convert.ToDecimal(2.8), 150);
      Worker Worker = chief;

      string output = GetString(Worker) + chief + " earned " +
      chief.Income().ToString("C") + "\n\n";

      Worker = Commemp;
      output += GetString(Worker) + Commemp +
      " earned "+Commemp.Income().ToString("C") + "\n\n";

      Worker = piece_emp;
      output += GetString(Worker) + piece_emp +
      " earned " + piece_emp.Income().ToString("C") +"\n\n";

      Console.WriteLine(output,"Polymorphism in use");
  } 

Now we will return a string of each worker class:

  // Worker informations 
  public static string GetString(Worker worker)
  {
    return worker.ToString() + " earned " +
       worker.Income().ToString("C") + "\n";
  }
} 

Polymorphism output

Boss: Khaled Sans earned $800.00
Boss: Khaled Sans earned $800.00

CommissionWorker: Susan Jons earned $540.00
CommissionWorker: Susan Jons earned $540.00

PieceWorker: samir Muan earned $420.00
PieceWorker: samir Muan earned $420.00

Conclusion

In this tutorial, we have learned about polymorphism and how useful it is when defining a generic abstract idea with different examples and classes, we have also learned how to use an abstract class to define other inherited classes from it.

Don't forget to test out and go through the code to completely understand how it works.

Further reading


Peer Review Contributions by: Mohan Raj

Published on: Jul 13, 2021
Updated on: Jul 12, 2024
CTA

Start your journey with Cloudzilla

With Cloudzilla, apps freely roam across a global cloud with unbeatable simplicity and cost efficiency