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.
- public abstract class Class_Abstract
- {
-
- }
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.
- abstract class Demo
- {
- public int Int1 { get; set; }
-
- public abstract int Int2
- {
- get;
- set;
- }
-
- public Demo()
- {
- Console.WriteLine("Demo Constructor");
- }
-
- public void Method1()
- {
- Console.WriteLine("Demo Method1");
- }
-
- public abstract void Method2();
-
- ~Demo()
- {
- Console.WriteLine("Demo Destructor");
- }
-
- }
-
- class Drived : Demo
- {
- public int Val;
- public override int Int2
- {
- get
- {
- return Val;
- }
- set
- {
- Val=value;
- }
- }
-
- public override void Method2()
- {
- Console.WriteLine("Drived Method2");
- }
- }
- class Program
- {
- static unsafe void Main(string[] args)
- {
-
- Drived Dr = new Drived();
- Dr.Int1 = 10;
- Dr.Int2 = 20;
- Dr.Method1();
- Dr.Method2();
- Console.ReadLine();
- }
-
- }
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.
-
- abstract class Shape1
- {
-
- protected float R, L, B;
-
-
- public abstract float Area();
- public abstract float Circumference();
- }
-
- class Rectangle1 : Shape1
- {
- public void GetLB()
- {
- Console.Write("Enter Length : ");
-
- L = float.Parse(Console.ReadLine());
-
- Console.Write("Enter Breadth : ");
-
- B = float.Parse(Console.ReadLine());
- }
-
-
- public override float Area()
- {
- return L * B;
- }
-
- public override float Circumference()
- {
- return 2 * (L + B);
- }
- }
-
- class Circle1 : Shape1
- {
-
- public void GetRadius()
- {
-
- Console.Write("Enter Radius : ");
- R = float.Parse(Console.ReadLine());
- }
-
- public override float Area()
- {
- return 3.14F * R * R;
- }
- public override float Circumference()
- {
- return 2 * 3.14F * R;
- }
- }
-
- class Program
- {
- public static void Calculate(Shape1 S)
- {
-
- Console.WriteLine("Area : {0}", S.Area());
- Console.WriteLine("Circumference : {0}", S.Circumference());
- }
- static unsafe void Main(string[] args)
- {
-
- Rectangle1 R = new Rectangle1();
- R.GetLB();
- Calculate(R);
-
- Console.WriteLine();
-
- Circle1 C = new Circle1();
- C.GetRadius();
- Calculate(C);
- Console.ReadLine();
- }
- }
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:
- abstract class Demo()
- {
- private abstract void Call();
- }
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:
- abstract class Demo()
- {
- abstract protected void Call();
- }
-
- class Drived:Demo
- {
- protected override void Call()
- {
-
- }
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:
- abstract sealed class Demo()
- {
- }
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:
- abstract class Demo()
- {
- abstract virtual public void Call();
-
- virtual abstract public void Call();
- };
An abstract method cannot have the modifier virtual because an abstract method is implicitly virtual.
Abstract class inherited from Interface(s)
- public interface IFace
- {
- void Call();
- void Demo();
- }
-
- public abstract class IDriv : IFace
- {
- public void Call()
- {
- Console.WriteLine("Call Method");
- }
- public abstract void Demo();
- }
-
-
- public class Drived:IDriv
- {
- public override void Demo()
- {
- Console.WriteLine("Demo Method");
- }
- }
-
- class Program
- {
-
- static unsafe void Main(string[] args)
- {
- Drived Dr = new Drived();
- Dr.Call();
- Dr.Demo();
-
- Console.ReadLine();
- }
-
- }
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
- abstract class Demo
- {
- public const int Int_ = 30;
- public readonly int Int2;
-
- public Demo()
- {
- Int2 = 100;
- }
-
- abstract public void Call();
- }
-
- class Drived : Demo
- {
- public override void Call()
- {
- Console.WriteLine(" Int_ ={0} Int2= {1}", Int_, Int2);
- }
- }
- class Program
- {
-
- static unsafe void Main(string[] args)
- {
- Drived Dr = new Drived();
- Dr.Call();
- Console.ReadLine();
- }
-
- }
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.
- abstract class Demo
- {
- public const int Int_ = 30;
- public readonly int Int2;
-
- public Demo()
- {
- Int2 = 100;
- }
-
- abstract public void Call();
- }
-
- class Drived : Demo
- {
- public override void Call()
- {
- Console.WriteLine(" Int_ ={0} Int2= {1}", Int_, Int2);
- }
- }
-
- class Assign : Drived
- {
- public override void Call()
- {
- Console.WriteLine("pankaj");
- }
- }
- class Program
- {
-
- static unsafe void Main(string[] args)
- {
- Assign Dr = new Assign();
- Dr.Call();
- Console.ReadLine();
- }
-
- }
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:
- abstract class Demo
- {
- public const int Int_ = 30;
- public readonly int Int2;
-
- public Demo()
- {
- Int2 = 100;
- }
-
- abstract public void Call();
- }
-
- class Drived : Demo
- {
- public sealed override void Call()
- {
- Console.WriteLine(" Int_ ={0} Int2= {1}", Int_, Int2);
- }
- }
-
- class Assign : Drived
- {
- public override void Call()
- {
- Console.WriteLine("pankaj");
- }
- }
- class Program
- {
-
- static unsafe void Main(string[] args)
- {
- Assign Dr = new Assign();
- Dr.Call();
- Console.ReadLine();
- }
-
- }
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.