Join the social network of Tech Nerds, increase skill rank, get work, manage projects...
 
  • Abstract Classes-Why and How?

    • 0
    • 0
    • 0
    • 0
    • 0
    • 0
    • 0
    • 0
    • 262
    Comment on it

    Hi Friends,

    Previously in one of my blogs (actually two of them) I was trying to decompress the very compressed definition of delegates that it is a pointer to a methods. Here we will try to decompress another definition or statements for an abstract class.

    So technically abstract class is a class which:

    1-Is declared with abstract keyword.
    2-Has at least one abstract method and that is implemented in derived classes.
    3-Is not sealed.
    4-Can’t be instantiated.
    5-Can’t be static

    So these are technical aspects and whenever you say something like this to someone, he gets assured that you (or me) know all about abstract classes. Boom! Interview done, you are selected and good to go with you shiny new job.

    But we all know that Microsoft didn’t create these classes specifically and only for interview questions. They have a purpose associated with them. You can write code without abstract classes and that will work fine. Inheriting from a base class helps us keeping common code at one place hence defining proper architecture and overriding a method helps us define different versions of same method which may differ in implementation.

    So continuing with abstract class, we can have following points to discuss:

    1-Why use an abstract class?
    2-Is there an obligation?
    3-Other options and their scenarios.

    1-Why use an abstract class?

    So why do we use an abstract class? I’d say an abstract class is specifically designed for the cleaner architecture of your code. By using it we can define our common code (which is lying around there in multiple classes inside your solution) here and define an abstract (in layman terms- which is not clear yet) method which you can override in your subsequent derived methods. So Let us see that with an example.

    For this we will take the example of a portion of any payroll management system which defines the (suppose) payment system for permanent employee and contract employee.  Permanent employee gets the monthly salary and contract employee gets hourly wages (say rupees 100 per hour).

    So in a simple scenarios we can define our code for permanent employee like following:

    public class PermanentEmployee
    {
        public string Name { get; set; }
        public string StreetName { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public int AnnualSalary { get; set; }
    
        public string GetEmployeeName()
        {
            return this.Name;
        }
    public string GetEmployeeAddress()
        {
            return this.StreetName + " ," + this.City + ,+ this.State;
        }
        public int GetMonthlySalary()
        {
            return this.AnnualSalary / 12;
        }
    }

    And code for contract employee:

    public class ContractEmployee
    {
        public string Name { get; set; }
        public string StreetName { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public int HoursWorked { get; set; }
        public int HourlyPay { get; set; }
    
        public string GetEmployeeName()
        {
            return this.Name;
        }
    public string GetEmployeeAddress()
        {
            return this.StreetName + " ," + this.City + ,+ this.State;
        }
        public int GetMonthlySalary()
        {
            return this. HoursWorked * this. HourlyPay;
        }
    }

    Finally the Program Class for main method:

    class Program
        {
            static void Main(string[] args)
            {
                
                Console.WriteLine("------Permanent Employee------");
                PermanentEmployee pe = new PermanentEmployee()
                {
                    Name = "Manvendra",
                    StreetName = "Haridwar Road",
                    City ="Dehradun",
                    State ="Uttarakhand",
                    AnnualSalary = 50000,
    
                };
    
                Console.WriteLine(pe.GetEmployeeName());
                Console.WriteLine(pe.GetEmployeeAddress());
                Console.WriteLine(pe.GetMonthlySalary());
    
                Console.WriteLine("------Contract Employee------");
    
                ContractEmployee ce = new ContractEmployee()
                {
                    Name = "Mayank",
                    StreetName = "Shimla Road",
                    City ="Dehradun",
                    State ="Uttarakhand",
                    HoursWorked = 20,
                    HourlyPay = 100
                };
    
                Console.WriteLine(ce.GetEmployeeName());
                Console.WriteLine(ce.GetEmployeeAddress());
                Console.WriteLine(ce.GetMonthlySalary());
                Console.Read();
    
            }
        }

    So in the above code we get the Name, Address and Salary or Wages based on the employee type, nothing wrong. But I think you can notice the repetition here. We are repeating some of the code each time. Apart from the method which is calculating salary, almost everything is repeated.

    Solution? Just move the common code to a single class and make other classes (Permanent Employee and Contract Employee) inherit from it. So we can move following members to a base class:

    Properties:-

    public string Name { get; set; }
    public string StreetName { get; set; }
    public string City { get; set; }
    public string State { get; set; }

    Methods:

    public string GetEmployeeName()
     {
          return this.Name;
      }
     public string GetEmployeeAddress()
       {
           return this.StreetName + " ," + this.City + ","+this.State;
       }

    Now the “GetMonthlySalary” method is defined differently in both of the classes, so we can make it as virtual and can override it derived classes, just perfect, right? So let us get to it:

    public class BaseEmployee
        {
            public string Name { get; set; }
            public string StreetName { get; set; }
            public string City { get; set; }
            public string State { get; set; }
            public string GetEmployeeName()
            {
                return this.Name;
            }
            public string GetEmployeeAddress()
            {
                return this.StreetName + " ," + this.City + "," + this.State;
            }
            public virtual int GetMonthlySalary()
            {
                throw new NotImplementedException();
            }
        }
    public class PermanentEmployee :BaseEmployee
        {
            
            public int AnnualSalary { get; set; }
    
            
            public override int GetMonthlySalary()
            {
                return this.AnnualSalary / 12;
            }
        }
        public class ContractEmployee:BaseEmployee
        {
            public int HoursWorked { get; set; }
            public int HourlyPay { get; set; }
    
            public override int GetMonthlySalary()
            {
                return this.HoursWorked * this.HourlyPay;
            }
        }

    The class containing main function remains the same. The code looks good and we’ve almost no repetition in our code. But we have another problem. We can create the object of our base class named “BaseEmployee” and this is a big issue because one will create an object of the class and try to call the “GetMonthlySalary” method which will result in an exception.

    Sot his code has following issues:

    1-Base class should not be insatiable.
    2-It throws an exception when BaseEmployee class object calls the “GetMonthlySalary” method (and that is obvious).
    3-Implementing a method with any exception is never a good idea. Even if there is something else there in the BaseEmployee class “GetMonthlySalary”, it will not be called because concept wise we have only Permanent and Contract Employee. There is nothing like BaseEmployee. So as said above in point 1, the BaseEmployee should not be instantiable.

    Now the abstract class comes into play. We will define the BaseEmployee  class as abstract class,  make the “GetMonthlySalary” as abstract and will continue to override the “GetMonthlySalary” method. This will make the BaseEmployee class non instantiable.

    And if we see the concept of any payroll system, there is nothing like base employee, it is just and imaginary term which we refer too so that we can define common properties for employee or you can say that it is just an idea which is in thought, nothing concrete.  So if someone asks you about the abstract class now- you can say that abstract class is a class which is “abstract”- now you know what abstract is.

    So now our code changes to:

    public abstract class BaseEmployee
        {
            public string Name { get; set; }
            public string StreetName { get; set; }
            public string City { get; set; }
            public string State { get; set; }
            public string GetEmployeeName()
            {
                return this.Name;
            }
            public string GetEmployeeAddress()
            {
                return this.StreetName + " ," + this.City + "," + this.State;
            }
            public abstract int GetMonthlySalary();
            
    
            
        }
    public class ContractEmployee:BaseEmployee
        {
            public int HoursWorked { get; set; }
            public int HourlyPay { get; set; }
    
            public override int GetMonthlySalary()
            {
                return this.HoursWorked * this.HourlyPay;
            }
        }
    public class PermanentEmployee :BaseEmployee
        {
            
            public int AnnualSalary { get; set; }
    
            
            public override int GetMonthlySalary()
            {
                return this.AnnualSalary / 12;
            }
        }
    

    Now you can see that we’ve achieved all of our objectives. We have no code redundancy and the base class is not instantiated. Only PermanentEmployee and ContractEmployee classes can be instantiated.

    Now that we can see about the use of the abstract class, we can discuss the point 2:

     

    2-Is there an obligation?

    Definitely not. There is no obligation to use them and you can write a perfectly “working” code without them. But after a certain amount of code and files, your perfectly working code will turn into a nightmare of maintenance.

    So for the maintainability sake abstract classes are very good options and mostly used in defining various architectural patterns.

    3-Other Scenarios.

    There may be an endless debate about using Interfaces in place of Abstract classes. And you can use them interchangeably as long as you don’t have any default implementation to go with. If you have any default implementation, go with abstract class. If you only have the contracts and no default or any implementation, go with interfaces.

    Thank You.

    Happy Coding.:-)

     

 0 Comment(s)

Sign In
                           OR                           
                           OR                           
Register

Sign up using

                           OR                           
Forgot Password
Fill out the form below and instructions to reset your password will be emailed to you:
Reset Password
Fill out the form below and reset your password: