Abstract Classes In C#

An abstract class is a special type of class that cannot be instantiated and acts as a base class for other classes. Abstract class members marked as abstract must be implemented by derived classes. The purpose of an abstract class is to provide a common definition of the base class that multiple derived classes can share and can be used only as a base class and never want to create the object of this class. Any class can be converted into an abstract class by adding the abstract modifier to it. Common features of an abstract class.

  1. public abstract class Class_Abstract  
  2.     {  
  3.         // Abstract Class Code.  
  4.     }  

Contents

An abstract class may contain the following:

  • Non-Abstract Method
  • Abstract method
  • Non Abstract Property
  • Abstract Property
  • Constructor
  • Destructor

Example

The following is an example.

  1. abstract class Demo  
  2.     {  
  3.         public int Int1 { getset; } //Non Abstract property  
  4.   
  5.         public abstract int Int2  //Abstract Property  
  6.         {  
  7.             get;  
  8.             set;  
  9.         }  
  10.   
  11.         public  Demo()  //Constructor  
  12.         {  
  13.             Console.WriteLine("Demo Constructor");  
  14.         }  
  15.   
  16.         public void Method1()   //Non Abstract Method  
  17.         {  
  18.             Console.WriteLine("Demo Method1");  
  19.         }  
  20.   
  21.         public abstract void Method2();  //Abstract Method  
  22.   
  23.          ~Demo()  //Destructor  
  24.         {  
  25.             Console.WriteLine("Demo Destructor");  
  26.         }  
  27.           
  28.     }  
  29.   
  30.     class Drived : Demo  
  31.     {  
  32.         public int Val;  
  33.         public override int Int2  
  34.         {  
  35.             get  
  36.             {  
  37.                 return Val;  
  38.             }  
  39.             set  
  40.             {  
  41.                 Val=value;  
  42.             }  
  43.         }  
  44.   
  45.         public override void Method2()  
  46.         {  
  47.             Console.WriteLine("Drived Method2");  
  48.         }  
  49.     }  
  50.     class Program  
  51.     {  
  52.         static unsafe void Main(string[] args)  
  53.         {  
  54.   
  55.             Drived Dr = new Drived();  
  56.             Dr.Int1 = 10;  
  57.             Dr.Int2 = 20;  
  58.             Dr.Method1();  
  59.             Dr.Method2();  
  60.             Console.ReadLine();  
  61.         }     
  62.   
  63.     }  

Output

The output is:



Use the abstract modifier in a class declaration to indicate that a class is intended only to be a base class of other classes. Members marked as abstract, or included in an abstract class, must be implemented by classes that derive from the abstract class.

The following is another example of an abstract class that will enhance the concept of abstract classes even more.

  1. //Abstract class  
  2.     abstract class Shape1  
  3.     {  
  4.   
  5.         protected float R, L, B;  
  6.   
  7.         //Abstract methods can have only declarations  
  8.         public abstract float Area();  
  9.         public abstract float Circumference();  
  10.     }  
  11.   
  12.     class Rectangle1 : Shape1  
  13.     {  
  14.         public void GetLB()  
  15.         {  
  16.             Console.Write("Enter  Length  :  ");  
  17.   
  18.             L = float.Parse(Console.ReadLine());  
  19.   
  20.             Console.Write("Enter Breadth : ");  
  21.   
  22.             B = float.Parse(Console.ReadLine());  
  23.         }  
  24.   
  25.   
  26.         public override float Area()  
  27.         {  
  28.             return L * B;  
  29.         }  
  30.   
  31.         public override float Circumference()  
  32.         {  
  33.             return 2 * (L + B);  
  34.         }    
  35.     }  
  36.   
  37.     class Circle1 : Shape1  
  38.     {  
  39.   
  40.         public void GetRadius()  
  41.         {  
  42.   
  43.             Console.Write("Enter  Radius  :  ");  
  44.             R = float.Parse(Console.ReadLine());  
  45.         }  
  46.   
  47.         public override float Area()  
  48.         {  
  49.             return 3.14F * R * R;  
  50.         }  
  51.         public override float Circumference()  
  52.         {  
  53.             return 2 * 3.14F * R;
  54.         }  
  55.     }  
  56.   
  57.     class Program  
  58.     {  
  59.         public static void Calculate(Shape1 S)  
  60.         {  
  61.   
  62.             Console.WriteLine("Area : {0}", S.Area());  
  63.             Console.WriteLine("Circumference : {0}", S.Circumference());  
  64.         }  
  65.         static unsafe void Main(string[] args)  
  66.         {  
  67.   
  68.             Rectangle1 R = new Rectangle1();  
  69.             R.GetLB();  
  70.             Calculate(R);  
  71.   
  72.             Console.WriteLine();  
  73.   
  74.             Circle1 C = new Circle1();  
  75.             C.GetRadius();  
  76.             Calculate(C);  
  77.             Console.ReadLine();  
  78.         }     
  79.     }  

Output

The following will be the output:



In the preceding example, Calculate method takes a parameter of type Shape1 from which the rectangle1 and circle1 classes are inherited.

A base class type parameter can take a derived class object as an argument. Hence the calculate method can take either a rectangle1 or circle1 object as an argument and the actual argument in the parameter S will be determined only at runtime and hence this example is an example for runtime polymorphism.

Some Important Points About Abstract Classes

private

An abstract method cannot be private as in the following:

  1. abstract  class  Demo()  
  2.     {  
  3.        private abstract void Call();  
  4.     }  

If we use the private access specifier for an abstract method then it will throw an error, because if we declare an abstract method as private then the derived classes cannot override it and that is inconsistent with the rules of abstract classes. So we cannot use have a private access specifier for an abstract method.

The same

An access specifier should be the same as in the following:

  1. abstract class Demo()  
  2.     {  
  3.        abstract  protected   void Call();  
  4.     }  
  5.   
  6.     class Drived:Demo  
  7.     {  
  8.         protected override void Call()  
  9. {  
  10.     //Code of Class  
  11. }  

The access modifier of the abstract method should be the same in both the abstract class and its derived class. If you declare an abstract method as protected, it should be protected in its derived class. Otherwise, the compiler will raise an error.

sealed

An abstract class cannot be a sealed as in the following:

  1. abstract sealed class Demo()  
  2.     {  
  3.     }  

Because If we declare an abstract class as sealed then, according to the property of the sealed keyword, the demo class cannot be inherited but, according to the property of the abstract keyword, an abstract class should be inherited. So a conflict will exist. So an abstract class cannot be declared as sealed.

virtual

An abstract method cannot have the modifier virtual as in the following:

  1. abstract  class Demo()  
  2.     {  
  3.         abstract virtual public void Call();  
  4.   
  5.         virtual  abstract  public void Call();  
  6.   };  
An abstract method cannot have the modifier virtual because an abstract method is implicitly virtual.

Abstract class inherited from Interface(s)
  1. public interface IFace  
  2.     {  
  3.         void  Call();  
  4.         void  Demo();  
  5.     }  
  6.   
  7.     public abstract class IDriv : IFace  
  8.     {  
  9.         public void  Call()  
  10.         {  
  11.             Console.WriteLine("Call Method");  
  12.         }  
  13.         public abstract void  Demo();  
  14.     }  
  15.   
  16.   
  17.     public class Drived:IDriv  
  18.     {  
  19.         public override void Demo()  
  20.         {  
  21.             Console.WriteLine("Demo Method");  
  22.         }  
  23.     }  
  24.       
  25.     class Program  
  26.     {  
  27.          
  28.         static unsafe void Main(string[] args)  
  29.         {  
  30.             Drived Dr = new Drived();  
  31.             Dr.Call();  
  32.             Dr.Demo();  
  33.               
  34.             Console.ReadLine();  
  35.         }  
  36.   
  37.         }  
In the preceding example we have a an interface IFace that contains the two methods Call() and Demo(). An abstract class IDriv inherits this interface. An abstract class IDriv implements the Call() method of the interface and marks the method Demo() as abstract.  Now we have another class Drived that inherits IDriv and implements the abstract method of the IDriv class. 
Output:
 
An Abstract Class can Contain Constant and Readonly Variables
 
  1. abstract class Demo  
  2.     {  
  3.         public const int Int_ = 30;  
  4.         public readonly int Int2;  
  5.   
  6.         public  Demo()  
  7.         {  
  8.             Int2 = 100;  
  9.         }  
  10.   
  11.         abstract public void Call();  
  12.     }  
  13.   
  14.     class Drived : Demo  
  15.     {  
  16.         public override void Call()  
  17.         {  
  18.             Console.WriteLine("  Int_ ={0}  Int2= {1}", Int_, Int2);  
  19.         }  
  20.     }  
  21.     class Program  
  22.     {  
  23.           
  24.         static unsafe void Main(string[] args)  
  25.         {  
  26.             Drived Dr = new Drived();  
  27.             Dr.Call();  
  28.             Console.ReadLine();  
  29.         }  
  30.   
  31.         }  
Output



In an abstract class we can use constant and readonly variable such as simple variable. If we are using a readonly variable in an abstract class then we can assign the value of a readonly variable in the abstract class's contructor.

Use of Sealed Keyword In Case of Multilevel Inheritance

First we examine the following example.
  1. abstract class Demo  
  2.     {  
  3.         public const int Int_ = 30;  
  4.         public readonly int Int2;  
  5.   
  6.         public  Demo()  
  7.         {  
  8.             Int2 = 100;  
  9.         }  
  10.   
  11.         abstract public void Call();  
  12.     }  
  13.   
  14.     class Drived : Demo  
  15.     {  
  16.         public  override void Call()  
  17.         {  
  18.             Console.WriteLine("  Int_ ={0}  Int2= {1}", Int_, Int2);  
  19.         }  
  20.     }  
  21.   
  22.     class Assign : Drived  
  23.     {  
  24.         public override    void Call()  
  25.         {  
  26.             Console.WriteLine("pankaj");  
  27.         }  
  28.     }  
  29.     class Program  
  30.     {  
  31.           
  32.         static unsafe void Main(string[] args)  
  33.         {  
  34.             Assign  Dr = new Assign();  
  35.             Dr.Call();  
  36.             Console.ReadLine();  
  37.         }  
  38.   
  39.         }  
Output



In the preceding example we have an abstract class Demo and the class Drived inherits the Demo class. So it can override the abstract method of the Demo class. In the example the Assign class inherits the Drived class so it can also override the abstract method of the Demo class due to Multilevel Inheritance. If we want to avoid this problem then we can use the “Sealed“  Keyword in the Drived class. Like this:
  1. abstract class Demo  
  2.     {  
  3.         public const int Int_ = 30;  
  4.         public readonly int Int2;  
  5.   
  6.         public  Demo()  
  7.         {  
  8.             Int2 = 100;  
  9.         }  
  10.   
  11.         abstract public void Call();  
  12.     }  
  13.   
  14.     class Drived : Demo  
  15.     {  
  16.         public  sealed  override void Call()     //Use of sealed Keyword  
  17.         {  
  18.             Console.WriteLine("  Int_ ={0}  Int2= {1}", Int_, Int2);  
  19.         }  
  20.     }  
  21.   
  22.     class Assign : Drived  
  23.     {  
  24.         public override    void Call()  
  25.         {  
  26.             Console.WriteLine("pankaj");  
  27.         }  
  28.     }  
  29.     class Program  
  30.     {  
  31.           
  32.         static unsafe void Main(string[] args)  
  33.         {  
  34.             Assign  Dr = new Assign();  
  35.             Dr.Call();  
  36.             Console.ReadLine();  
  37.         }  
  38.   
  39.         }  
Output

Now if we run this program then the compiler will throw an error as in the following:


When Should we use an Abstract Class
  • When independency of a class is not required in your application.

  • If there are certain members/behaviors that are common to all classes, these should be placed inside the abstract class.

  • If we want to provide some method to a base class that must be implemented in a derived class then we can use an abstract class and make the method abstract. Which we want to implement in the derived class.