Constructors In Abstract Classes

Question: Can an abstract class have a constructor? If so what is the use?

Answer: Yes, an abstract class can have a constructor. In general, a class constructor is used to initialize fields. Along the same lines, an abstract class constructor is used to initialize fields of the abstract class.

Let's see an example.

Step 1

First we will create a console application named InterviewQuestionPart7.

console application

Step 2

Then we will create an abstract class named customer and include a private field, the return type of this private field is Guid that is a Globally Unique Identifier. Now to expose this field to the external world, let's include a public property and we want this property to be read-only and we will include only Get accesses.

Now for initializing this private field of the abstract class we will create a constructor within this abstract class that has the same name of the class and does not have a return type. So let's use this constructor to initialize the private field. We will therefore now initialize it as a new Globally Unique Identifier (GUID), so we will invoke the NewGuid() method on the Guid class using the following code.

  1. using System;   
  2. using System.Collections.Generic;   
  3. using System.Text;   
  4.   
  5. namespace InterviewQuestionPart7   
  6. {   
  7.    class Program   
  8.    {   
  9.       static void Main(string[] args)   
  10.       {   
  11.    
  12.       }   
  13.       public abstract class Customer   
  14.    
  15.       {   
  16.          public Customer()   
  17.          {   
  18.             this._id = Guid.NewGuid();   
  19.          }   
  20.          private Guid _id;   
  21.          public Guid ID   
  22.          {   
  23.             get   
  24.             {   
  25.                return this._id;   
  26.             }   
  27.          }   
  28.   
  29.       }   
  30.    
  31.    }   
  32. }   
Step 3
 
Now in our business we have two types of customers, CorporateCustomer and SavingsCustomer. We will create two classes, CorporateCustomer class and Savings Customer class, and they will be derived from our Customer abstract class.

Now we will create an instance of the CorporateCustomer class derived from the Customer class and the Customer class has the property public ID, so it should be available on the instance of CorporateCustomer class. And similarly we will create an instance of a SavingsCustomer class and print the property using the following code.
  1. using System;   
  2. using System.Collections.Generic;   
  3. using System.Text;   
  4.    
  5. namespace InterviewQuestionPart7   
  6. {   
  7.    class Program   
  8.    {   
  9.       static void Main(string[] args)   
  10.       {   
  11.           CorporateCustomer cc = new CorporateCustomer();   
  12.           Console.WriteLine(cc.ID);   
  13.    
  14.           SavingsCustomer sc = new SavingsCustomer();   
  15.           Console.WriteLine(sc.ID);   
  16.    
  17.       }   
  18.       public abstract class Customer   
  19.    
  20.       {   
  21.           public Customer()   
  22.           {   
  23.              this._id = Guid.NewGuid();   
  24.           }   
  25.           private Guid _id;   
  26.           public Guid ID   
  27.           {   
  28.              get   
  29.              {   
  30.                 return this._id;   
  31.              }   
  32.           }   
  33.    
  34.        }   
  35.        public class CorporateCustomer:Customer   
  36.        {   
  37.    
  38.        }   
  39.        public class SavingsCustomer:Customer   
  40.        {   
  41.    
  42.        }   
  43.     }   
  44.  }   
Now let's run and see the output we get. As expected we get the Globally Unique Identifier for the CorporateCustomer class and the SavingsCustomer class.

output

So here within the abstract class we are using the constructor to initialize the fields of the abstract class.


Step 4
 
We would provide a constructor for an abstract class if we want to initialize certain fields of the abstract class before the instantiation of a child class takes place.

Here we have two child classes, CorporateCustomer and SavingsCustomer, derived from the abstract Customer class.

Now we want a Globaly Unique Identifier to be assigned to the _id field, even before an instance of either the CorporateCustomer or SavingsCustomer to be created. this is another use case where we use a constructor within the abstract class.

Let's actually prove that the constructor of the abstract class is called before even the child class constructor. For proving that let's include the constructor in both of the derived classes with the following code.
  1. using System;   
  2. using System.Collections.Generic;   
  3. using System.Text;   
  4.   
  5. namespace InterviewQuestionPart7   
  6. {   
  7.    class Program   
  8.    {   
  9.       static void Main(string[] args)   
  10.       {   
  11.           CorporateCustomer cc = new CorporateCustomer();   
  12.           Console.WriteLine(cc.ID);   
  13.    
  14.           SavingsCustomer sc = new SavingsCustomer();   
  15.           Console.WriteLine(sc.ID);   
  16.    
  17.       }   
  18.       public abstract class Customer   
  19.    
  20.       {   
  21.           public Customer()   
  22.           {   
  23.              this._id = Guid.NewGuid();   
  24.           }   
  25.           private Guid _id;   
  26.           public Guid ID   
  27.           {   
  28.              get   
  29.              {   
  30.                 return this._id;   
  31.              }   
  32.           }   
  33.    
  34.        }   
  35.        public class CorporateCustomer:Customer   
  36.        {   
  37.           public CorporateCustomer()   
  38.           {   
  39.    
  40.           }   
  41.    
  42.        }   
  43.        public class SavingsCustomer:Customer   
  44.        {   
  45.    
  46.           public SavingsCustomer()   
  47.           {   
  48.    
  49.           }   
  50.        }   
  51.     }   
  52.  }   
Now we will create a breakpoint on the CorporateCustomer constructor and SavingsCustomer constructor, in the abstract class constructor and within the Main method. Now Debug the program and see what will happen.

First we try to create an instance of the CorporateCustomer derived class and now we will press F11/F10 until it gets to the CorporateCustomer constructor (that is the child class constructor) and try to execute it. Now we press the F10 and notice that what happens is it comes to the base class constructor. Now again we will press F10 and it executes and assigns the Globally Unique Identifier. Now again we will press the F10 and it will get to the constructor of the CorporateCustomer. Then it will execute the child class constructor. So that proves that the constructor of the parent class is called before the derived class constructor. So this this another use case where we would use the a constructor within the abstract class.

globly unique identifire

An abstract class constructor can also be used to execute code that is relevant for every child class.

This prevents duplicate code.

Step 5
 
Now if we look, the ID field is common to both the CorporateCustomer class and the SavingsCustomer class and it is present in the abstract class. If we were to move this code to the derived classes then we would end up with this duplicated code in both of the derived classes. Now we will move this code to both of the classes. And in the base class we remove the constructor and make the property abstract. And we need to override the property in the derived classes using the following code.
  1. using System;   
  2. using System.Collections.Generic;   
  3. using System.Text;   
  4.   
  5. namespace InterviewQuestionPart7   
  6. {   
  7.    class Program   
  8.    {   
  9.       static void Main(string[] args)   
  10.        {   
  11.           CorporateCustomer cc = new CorporateCustomer();   
  12.           Console.WriteLine(cc.ID);   
  13.    
  14.           SavingsCustomer sc = new SavingsCustomer();   
  15.           Console.WriteLine(sc.ID);   
  16.    
  17.        }   
  18.        public abstract class Customer   
  19.    
  20.        {   
  21.           public abstract Guid ID   
  22.           {   
  23.              get;   
  24.    
  25.           }   
  26.    
  27.        }   
  28.        public class CorporateCustomer:Customer   
  29.        {   
  30.           public CorporateCustomer()   
  31.           {   
  32.              this._id = Guid.NewGuid();   
  33.           }   
  34.           private Guid _id;   
  35.           public override Guid ID   
  36.           {   
  37.              get   
  38.              {   
  39.                 return this._id;   
  40.              }   
  41.           }   
  42.    
  43.        }   
  44.        public class SavingsCustomer:Customer   
  45.        {   
  46.    
  47.           public SavingsCustomer()   
  48.           {   
  49.              this._id = Guid.NewGuid();   
  50.           }   
  51.           private Guid _id;   
  52.           public override Guid ID   
  53.           {   
  54.              get   
  55.              {   
  56.                 return this._id;   
  57.              }   
  58.           }   
  59.        }   
  60.     }   
  61.  }   
Now we will run this and we will get the same output like this.

program output

But at the moment since we have delegated the responsibility of initializing the common field of the derived class we have duplicated code in both of the classes.

So an abstract class constructor can also be used to execute code that is relevant for every child class. This prevents duplicate code.

abstract class

Note: Abstract classes can't be directly instantiated. The abstract class constructor gets executed from a derived class. So, it is a good practice to use a protected access modifier with an abstract class constructor. Making it public doesn't make sense.

Step 6
 
Now to understand this we reset move back the implementation in the base class. We have the public constructor in the abstract class.

So we create an instance of the abstract class explicitly. Now to see what will happen, let's build it. We get an error. Here it makes sense.
  1. using System;   
  2. using System.Collections.Generic;   
  3. using System.Text;   
  4.   
  5. namespace InterviewQuestionPart7   
  6. {   
  7.    class Program   
  8.    {   
  9.       static void Main(string[] args)   
  10.        {   
  11.           //instance of base class   
  12.           Customer c = new Customer();   
  13.    
  14.           CorporateCustomer cc = new CorporateCustomer();   
  15.           Console.WriteLine(cc.ID);   
  16.    
  17.           SavingsCustomer sc = new SavingsCustomer();   
  18.           Console.WriteLine(sc.ID);   
  19.    
  20.        }   
  21.        public abstract class Customer   
  22.    
  23.        {   
  24.           public Customer()   
  25.           {   
  26.              this._id = Guid.NewGuid();   
  27.           }   
  28.           private Guid _id;   
  29.           public Guid ID   
  30.           {   
  31.              get   
  32.              {   
  33.                 return this._id;   
  34.              }   
  35.           }   
  36.    
  37.        }   
  38.        public class CorporateCustomer:Customer   
  39.        {   
  40.    
  41.        }   
  42.        public class SavingsCustomer:Customer   
  43.        {   
  44.    
  45.        }   
  46.     }   
  47.  }   
error

Step 7
 
Now the constructor of the abstract class is called from the derived class so it should be available in the derived class and we know that we cannot create an instance of the base class explicitly like this so having the access modifier public does not make sense so now we will use the protected modifier and it is a good practice so now the application runs in the same manner.
  1. using System;   
  2. using System.Collections.Generic;   
  3. using System.Text;   
  4.   
  5. namespace InterviewQuestionPart7   
  6. {   
  7.    class Program   
  8.    {   
  9.       static void Main(string[] args)   
  10.       {   
  11.    
  12.           CorporateCustomer cc = new CorporateCustomer();   
  13.           Console.WriteLine(cc.ID);   
  14.    
  15.           SavingsCustomer sc = new SavingsCustomer();   
  16.           Console.WriteLine(sc.ID);   
  17.    
  18.        }   
  19.        public abstract class Customer   
  20.    
  21.        {   
  22.           protected Customer()   
  23.           {   
  24.              this._id = Guid.NewGuid();   
  25.           }   
  26.           private Guid _id;   
  27.           public Guid ID   
  28.           {   
  29.              get   
  30.              {   
  31.                 return this._id;   
  32.              }   
  33.           }   
  34.    
  35.        }   
  36.        public class CorporateCustomer:Customer   
  37.        {   
  38.    
  39.        }   
  40.        public class SavingsCustomer:Customer   
  41.        {   
  42.    
  43.    
  44.        }   
  45.     }   
  46.  }   
Now we see the output as expected.

show output

 


Similar Articles